How to handle OPTIONS request in Cherrypy?
Edvin Beqari <[email protected]> Sun, 16 Jun 2019 16:01:29 -0700 (PDT)
| Newsgroups | gmane.comp.python.cherrypy |
|---|---|
| Message-ID | <[email protected]> |
------=_Part_1433_273778045.1560726089664
Content-Type: multipart/alternative;
boundary="----=_Part_1434_2096340590.1560726089665"
------=_Part_1434_2096340590.1560726089665
Content-Type: text/plain; charset="UTF-8"
I am trying to make a POST request with Axios to a Cherrypy server but I am
running into Cors issues.
*Axios client: *
try {
const data = JSON.stringify({
name: "Bob"
});
const request = await ServerApi.post('/catalog/input', data, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
} catch (e) {
console.log(`Failed to send inputs: ${e}`);
}
*Cherrypy server: *
import os
import os.path
import random
import string
import json
import cherrypy
from controller import Controller
class Server(object):
@cherrypy.expose
def index(self):
return open('../cococlient/build/index.html')
def CORS():
if cherrypy.request.method == 'OPTIONS':
cherrypy.response.headers['Access-Control-Allow-Methods'] = 'GET, POST,
PATCH, PUT, DELETE, OPTIONS'
cherrypy.response.headers['Access-Control-Allow-Headers'] = 'Origin,
Content-Type, Accept, Access-Control-Allow-Headers'
cherrypy.response.headers['Access-Control-Allow-Origin'] =
'http://127.0.0.1:3000'
cherrypy.response.headers['Access-Control-Max-Age'] = '3600'
return True
else:
cherrypy.response.headers['Access-Control-Allow-Origin'] =
'http://127.0.0.1:3000'
if __name__ == '__main__':
conf = {
'/': {
'tools.staticdir.root': os.path.abspath(os.getcwd())
},
'/catalog': {
'tools.CORS.on': True,
'tools.response_headers.on': True
},
'/static': {
'tools.staticdir.on': True,
'tools.staticdir.dir': '../cococlient/build/static'
}
}
server = Server()
server.catalog = Controller()
cherrypy.tools.CORS = cherrypy.Tool('before_handler', CORS)
cherrypy.quickstart(server, '/', conf)
And finally the Controller class with the input method:
import cherrypy
import json
import simplejson
from cherrypy import tools
from catalog import Catalog
class Controller(object):
@cherrypy.expose
@cherrypy.tools.json_in()
@cherrypy.tools.json_out()
def input(self):
data = cherrypy.request.json
return data.items()
So what happens is the POST method gets turned into OPTIONS which does not
include the payload;
and consequently the input method raises an error which says
"cherrypy.request" does not have an attribute "json."
So, how do I configure Cherrypy to return the pre-flight response headers
before calling the input method.
I am not sure how to proceed. Thank you.
--
You received this message because you are subscribed to the Google Groups "cherrypy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cherrypy-users+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
To post to this group, send email to cherrypy-users-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
Visit this group at https://groups.google.com/group/cherrypy-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/cherrypy-users/61d48ccb-15dd-4135-8327-10f1587cce79%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
------=_Part_1434_2096340590.1560726089665
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I am trying to make a POST request with Axios to a Cherryp=
y server but I am running into Cors issues.=C2=A0<div><br></div><div><i>Axi=
os client:=C2=A0</i></div><div><br></div><div><div style=3D"color: rgb(0, 0=
, 0); font-family: Consolas, "Courier New", monospace; line-heigh=
t: 19px; white-space: pre;"><div style=3D""><font size=3D"1"> <span styl=
e=3D"color: rgb(0, 0, 255);">try</span> {</font></div><div style=3D""><font=
size=3D"1"> <span style=3D"color: #0000ff;">const</span> data =3D JSO=
N.stringify({</font></div><div style=3D""><font size=3D"1"> name: <s=
pan style=3D"color: #a31515;">"Bob"</span></font></div><div style=
=3D""><font size=3D"1"> });</font></div><div style=3D""><font size=3D"=
1"><br></font></div><div style=3D""><font size=3D"1"> <span style=3D"c=
olor: #0000ff;">const</span> request =3D <span style=3D"color: #0000ff;">aw=
ait</span> ServerApi.post(<span style=3D"color: #a31515;">'/catalog/inp=
ut'</span>, data, {</font></div><div style=3D""><font size=3D"1"> =
headers: {</font></div><div style=3D""><font size=3D"1"> <span s=
tyle=3D"color: #a31515;">'Accept'</span>: <span style=3D"color: #a3=
1515;">'application/json'</span>,</font></div><div style=3D""><font=
size=3D"1"> <span style=3D"color: #a31515;">'Content-Type'=
;</span>: <span style=3D"color: #a31515;">'application/json'</span>=
</font></div><div style=3D""><font size=3D"1"> }</font></div><div st=
yle=3D""><font size=3D"1"> });</font></div><div style=3D""><font size=
=3D"1"><br></font></div><div style=3D""><font size=3D"1"> } <span style=
=3D"color: #0000ff;">catch</span> (e) {</font></div><div style=3D""><font s=
ize=3D"1"> console.log(<span style=3D"color: #a31515;">`Failed to send=
inputs: </span><span style=3D"color: #0000ff;">${</span>e<span style=3D"co=
lor: #0000ff;">}</span><span style=3D"color: #a31515;">`</span>);</font></d=
iv><div style=3D""><font size=3D"1"> }</font></div></div></div><div><br>=
</div><div><div style=3D"line-height: 19px;"><div style=3D"color: rgb(0, 0,=
0); font-family: Consolas, "Courier New", monospace; white-space=
: pre;"><font size=3D"2"><i>Cherrypy server: </i></font></div><div style=3D=
"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", monos=
pace; white-space: pre;"><font size=3D"2"><br></font></div><div style=3D"">=
<div style=3D"line-height: 19px;"><div style=3D"color: rgb(0, 0, 0); font-f=
amily: Consolas, "Courier New", monospace; white-space: pre;"><fo=
nt size=3D"1"><span style=3D"color: rgb(0, 0, 255);">import</span> os</font=
></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Cour=
ier New", monospace; white-space: pre;"><font size=3D"1"><span style=
=3D"color: #0000ff;">import</span> os.path</font></div><div style=3D"color:=
rgb(0, 0, 0); font-family: Consolas, "Courier New", monospace; w=
hite-space: pre;"><font size=3D"1"><span style=3D"color: #0000ff;">import</=
span> random</font></div><div style=3D"color: rgb(0, 0, 0); font-family: Co=
nsolas, "Courier New", monospace; white-space: pre;"><font size=
=3D"1"><span style=3D"color: #0000ff;">import</span> string</font></div><di=
v style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New&qu=
ot;, monospace; white-space: pre;"><font size=3D"1"><span style=3D"color: #=
0000ff;">import</span> json</font></div><div style=3D"color: rgb(0, 0, 0); =
font-family: Consolas, "Courier New", monospace; white-space: pre=
;"><font size=3D"1"><span style=3D"color: #0000ff;">import</span> cherrypy<=
/font></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "=
;Courier New", monospace; white-space: pre;"><font size=3D"1"><span st=
yle=3D"color: #0000ff;">from</span> controller <span style=3D"color: #0000f=
f;">import</span> Controller</font></div><div style=3D"color: rgb(0, 0, 0);=
font-family: Consolas, "Courier New", monospace; white-space: pr=
e;"><font size=3D"1"><br></font></div><div style=3D"color: rgb(0, 0, 0); fo=
nt-family: Consolas, "Courier New", monospace; white-space: pre;"=
><font size=3D"1"><span style=3D"color: #0000ff;">class</span> Server(objec=
t):</font></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, &=
quot;Courier New", monospace; white-space: pre;"><font size=3D"1"><br>=
</font></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, &quo=
t;Courier New", monospace; white-space: pre;"><font size=3D"1"> @ch=
errypy.expose</font></div><div style=3D"color: rgb(0, 0, 0); font-family: C=
onsolas, "Courier New", monospace; white-space: pre;"><font size=
=3D"1"> <span style=3D"color: #0000ff;">def</span> index(self):</font></=
div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier=
New", monospace; white-space: pre;"><font size=3D"1"> <span st=
yle=3D"color: #0000ff;">return</span> open(<span style=3D"color: #a31515;">=
'../cococlient/build/index.html'</span>)</font></div><font size=3D"=
1" style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New&q=
uot;, monospace; white-space: pre;"><br></font><div style=3D"color: rgb(0, =
0, 0); font-family: Consolas, "Courier New", monospace; white-spa=
ce: pre;"><font size=3D"1"><span style=3D"color: #0000ff;">def</span> CORS(=
):</font></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, &q=
uot;Courier New", monospace; white-space: pre;"><font size=3D"1"> <=
span style=3D"color: #0000ff;">if</span> cherrypy.request.method =3D=3D <sp=
an style=3D"color: #a31515;">'OPTIONS'</span>:</font></div><div sty=
le=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", =
monospace; white-space: pre;"><font size=3D"1"> cherrypy.response.he=
aders[<span style=3D"color: #a31515;">'Access-Control-Allow-Methods'=
;</span>] =3D <span style=3D"color: #a31515;">'GET, POST, PATCH, PUT, D=
ELETE, OPTIONS'</span></font></div><div style=3D"color: rgb(0, 0, 0); f=
ont-family: Consolas, "Courier New", monospace; white-space: pre;=
"><font size=3D"1"> cherrypy.response.headers[<span style=3D"color: =
#a31515;">'Access-Control-Allow-Headers'</span>] =3D <span style=3D=
"color: #a31515;">'Origin, Content-Type, Accept, Access-Control-Allow-H=
eaders'</span></font></div><div style=3D"color: rgb(0, 0, 0); font-fami=
ly: Consolas, "Courier New", monospace; white-space: pre;"><font =
size=3D"1"> cherrypy.response.headers[<span style=3D"color: #a31515;=
">'Access-Control-Allow-Origin'</span>] =3D <span style=3D"color: =
#a31515;">'http://127.0.0.1:3000'</span></font></div><div style=3D"=
color: rgb(0, 0, 0); font-family: Consolas, "Courier New", monosp=
ace; white-space: pre;"><font size=3D"1"> cherrypy.response.headers[=
<span style=3D"color: #a31515;">'Access-Control-Max-Age'</span>] =
=3D <span style=3D"color: #a31515;">'3600'</span></font></div><div =
style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New"=
;, monospace; white-space: pre;"><font size=3D"1"> <span style=3D"co=
lor: #0000ff;">return</span> <span style=3D"color: #0000ff;">True</span></f=
ont></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "C=
ourier New", monospace; white-space: pre;"><font size=3D"1"> <span =
style=3D"color: #0000ff;">else</span>:</font></div><div style=3D"color: rgb=
(0, 0, 0); font-family: Consolas, "Courier New", monospace; white=
-space: pre;"><font size=3D"1"> cherrypy.response.headers[<span styl=
e=3D"color: #a31515;">'Access-Control-Allow-Origin'</span>] =3D <s=
pan style=3D"color: #a31515;">'http://127.0.0.1:3000'</span></font>=
</div><font size=3D"1" style=3D"color: rgb(0, 0, 0); font-family: Consolas,=
"Courier New", monospace; white-space: pre;"><br></font><div sty=
le=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", =
monospace; white-space: pre;"><font size=3D"1"><span style=3D"color: #0000f=
f;">if</span> __name__ =3D=3D <span style=3D"color: #a31515;">'__main__=
'</span>:</font></div><div style=3D"color: rgb(0, 0, 0); font-family: C=
onsolas, "Courier New", monospace; white-space: pre;"><font size=
=3D"1"> conf =3D {</font></div><div style=3D"color: rgb(0, 0, 0); font-f=
amily: Consolas, "Courier New", monospace; white-space: pre;"><fo=
nt size=3D"1"> <span style=3D"color: #a31515;">'/'</span>: {=
</font></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, &quo=
t;Courier New", monospace; white-space: pre;"><font size=3D"1"> =
<span style=3D"color: #a31515;">'tools.staticdir.root'</span>:=
os.path.abspath(os.getcwd())</font></div><div style=3D"color: rgb(0, 0, 0)=
; font-family: Consolas, "Courier New", monospace; white-space: p=
re;"><font size=3D"1"> },</font></div><div style=3D"color: rgb(0, 0,=
0); font-family: Consolas, "Courier New", monospace; white-space=
: pre;"><font size=3D"1"> <span style=3D"color: #a31515;">'/cata=
log'</span>: {</font></div><div style=3D"color: rgb(0, 0, 0); font-fami=
ly: Consolas, "Courier New", monospace; white-space: pre;"><font =
size=3D"1"> <span style=3D"color: #a31515;">'tools.CORS.on&#=
39;</span>: <span style=3D"color: #0000ff;">True</span>,</font></div><div s=
tyle=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New"=
, monospace; white-space: pre;"><font size=3D"1"> <span style=3D=
"color: #a31515;">'tools.response_headers.on'</span>: <span style=
=3D"color: #0000ff;">True</span></font></div><div style=3D"color: rgb(0, 0,=
0); font-family: Consolas, "Courier New", monospace; white-space=
: pre;"><font size=3D"1"> },</font></div><div style=3D"color: rgb(0,=
0, 0); font-family: Consolas, "Courier New", monospace; white-sp=
ace: pre;"><font size=3D"1"> <span style=3D"color: #a31515;">'/s=
tatic'</span>: {</font></div><div style=3D"color: rgb(0, 0, 0); font-fa=
mily: Consolas, "Courier New", monospace; white-space: pre;"><fon=
t size=3D"1"> <span style=3D"color: #a31515;">'tools.staticd=
ir.on'</span>: <span style=3D"color: #0000ff;">True</span>,</font></div=
><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier Ne=
w", monospace; white-space: pre;"><font size=3D"1"> <span s=
tyle=3D"color: #a31515;">'tools.staticdir.dir'</span>: <span style=
=3D"color: #a31515;">'../cococlient/build/static'</span></font></di=
v><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier N=
ew", monospace; white-space: pre;"><font size=3D"1"> }</font></=
div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier=
New", monospace; white-space: pre;"><font size=3D"1"> }</font></di=
v><font size=3D"1" style=3D"color: rgb(0, 0, 0); font-family: Consolas, &qu=
ot;Courier New", monospace; white-space: pre;"><br></font><div style=
=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", mo=
nospace; white-space: pre;"><font size=3D"1"> server =3D Server()</font>=
</div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Couri=
er New", monospace; white-space: pre;"><font size=3D"1"> server.cat=
alog =3D Controller()</font></div><div style=3D"color: rgb(0, 0, 0); font-f=
amily: Consolas, "Courier New", monospace; white-space: pre;"><fo=
nt size=3D"1"> cherrypy.tools.CORS =3D cherrypy.Tool(<span style=3D"colo=
r: #a31515;">'before_handler'</span>, CORS)</font></div><font size=
=3D"1" style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier N=
ew", monospace; white-space: pre;"><br></font><div style=3D"color: rgb=
(0, 0, 0); font-family: Consolas, "Courier New", monospace; white=
-space: pre;"><font size=3D"1"> cherrypy.quickstart(server, <span style=
=3D"color: rgb(163, 21, 21);">'/'</span>, conf)</font></div><div st=
yle=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New",=
monospace; white-space: pre;"><font size=3D"1"><br></font></div><div style=
=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", mo=
nospace; white-space: pre;"><font size=3D"1">And finally the Controller cla=
ss with the input method: </font></div><div style=3D"color: rgb(0, 0, 0); f=
ont-family: Consolas, "Courier New", monospace; white-space: pre;=
"><font size=3D"1"><br></font></div><div style=3D""><div style=3D"line-heig=
ht: 19px;"><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "=
Courier New", monospace; white-space: pre;"><font size=3D"1"><span sty=
le=3D"color: rgb(0, 0, 255);">import</span> cherrypy</font></div><div style=
=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", mo=
nospace; white-space: pre;"><font size=3D"1"><span style=3D"color: #0000ff;=
">import</span> json</font></div><div style=3D"color: rgb(0, 0, 0); font-fa=
mily: Consolas, "Courier New", monospace; white-space: pre;"><fon=
t size=3D"1"><span style=3D"color: #0000ff;">import</span> simplejson</font=
></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Cour=
ier New", monospace; white-space: pre;"><font size=3D"1"><span style=
=3D"color: #0000ff;">from</span> cherrypy <span style=3D"color: #0000ff;">i=
mport</span> tools</font></div><div style=3D"color: rgb(0, 0, 0); font-fami=
ly: Consolas, "Courier New", monospace; white-space: pre;"><font =
size=3D"1"><span style=3D"color: #0000ff;">from</span> catalog <span style=
=3D"color: #0000ff;">import</span> Catalog</font></div><div style=3D"color:=
rgb(0, 0, 0); font-family: Consolas, "Courier New", monospace; w=
hite-space: pre;"><font size=3D"1"><br></font></div><div style=3D"color: rg=
b(0, 0, 0); font-family: Consolas, "Courier New", monospace; whit=
e-space: pre;"><font size=3D"1"><span style=3D"color: #0000ff;">class</span=
> Controller(object):</font></div><div style=3D"color: rgb(0, 0, 0); font-f=
amily: Consolas, "Courier New", monospace; white-space: pre;"><br=
></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Cour=
ier New", monospace; white-space: pre;"><font size=3D"1"> @cherrypy=
.expose</font></div><div style=3D"color: rgb(0, 0, 0); font-family: Consola=
s, "Courier New", monospace; white-space: pre;"><font size=3D"1">=
@cherrypy.tools.json_in()</font></div><div style=3D"color: rgb(0, 0, 0)=
; font-family: Consolas, "Courier New", monospace; white-space: p=
re;"><font size=3D"1"> @cherrypy.tools.json_out()</font></div><div style=
=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", mo=
nospace; white-space: pre;"><font size=3D"1"> <span style=3D"color: #000=
0ff;">def</span> input(self):</font></div><div style=3D"color: rgb(0, 0, 0)=
; font-family: Consolas, "Courier New", monospace; white-space: p=
re;"><font size=3D"1"> data =3D cherrypy.request.json</font></div><d=
iv style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New&q=
uot;, monospace; white-space: pre;"><font size=3D"1"> <span style=3D=
"color: rgb(0, 0, 255);">return</span> data.items()</font></div><div style=
=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", mo=
nospace; white-space: pre;"><font size=3D"1"><br></font></div><div style=3D=
"color: rgb(0, 0, 0); font-family: Consolas, "Courier New", monos=
pace; white-space: pre;"><font size=3D"2">So what happens is the POST metho=
d gets turned into OPTIONS which does not include the payload;</font></div>=
<div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New=
", monospace; white-space: pre;"><span style=3D"font-size: small;">and=
consequently the input method raises an error which says "cherrypy.re=
quest" does not have an attribute "json."</span></div><div s=
tyle=3D"color: rgb(0, 0, 0); font-family: Consolas, "Courier New"=
, monospace; white-space: pre;"><span style=3D"font-size: small;"><br></spa=
n></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Cou=
rier New", monospace; white-space: pre;"><span style=3D"font-size: sma=
ll;">So, how do I configure Cherrypy to return the pre-flight response head=
ers before calling the input method. </span></div><div style=3D"color: rgb(=
0, 0, 0); font-family: Consolas, "Courier New", monospace; white-=
space: pre;"><span style=3D"font-size: small;"><br></span></div><div style=
=3D""><font size=3D"2" style=3D"color: rgb(0, 0, 0); font-family: Consolas,=
"Courier New", monospace; white-space: pre;">I am not sure how t=
o </font><font color=3D"#000000" face=3D"Consolas, Courier New, monospace" =
size=3D"2"><span style=3D"white-space: pre;">proceed. Thank you.</span></fo=
nt></div><div style=3D"color: rgb(0, 0, 0); font-family: Consolas, "Co=
urier New", monospace; white-space: pre;"><span style=3D"font-size: sm=
all;"> </span></div></div></div><div style=3D"color: rgb(0, 0, 0); font-fa=
mily: Consolas, "Courier New", monospace; white-space: pre;"><fon=
t size=3D"1"><br></font></div></div></div><div style=3D"color: rgb(0, 0, 0)=
; font-family: Consolas, "Courier New", monospace; white-space: p=
re;"><br></div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;cherrypy-users" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:cherrypy-users+unsubscribe-/[email protected]">cher=
rypy-users+unsubscribe-/[email protected]</a>.<br />
To post to this group, send email to <a href=3D"mailto:cherrypy-users@googl=
egroups.com">cherrypy-users-/[email protected]</a>.<br />
Visit this group at <a href=3D"https://groups.google.com/group/cherrypy-use=
rs">https://groups.google.com/group/cherrypy-users</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/d/msgid/cherrypy-users/61d48ccb-15dd-4135-8327-10f1587cce79%40googlegrou=
ps.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.com/d/=
msgid/cherrypy-users/61d48ccb-15dd-4135-8327-10f1587cce79%40googlegroups.co=
m</a>.<br />
For more options, visit <a href=3D"https://groups.google.com/d/optout">http=
s://groups.google.com/d/optout</a>.<br />
------=_Part_1434_2096340590.1560726089665--
------=_Part_1433_273778045.1560726089664--