Axios is adding a prefix to the api target url - flask

I know this may be the dumpest question ever asked, however it really got me this hopeless :(
I have the React front End with a simple property in package.json
"proxy": "http://localhost:5000/"
which I believe is redirecting all api sent through axios to that servr address.
My axios request is
const canvas_type="standard"
axios.post('api/v1/new_canvas',{
canvas_type
})
}
The backend flask api is:
#api_bp.route("/new_canvas", methods=["POST"])
#requires_auth
def get_new_cavas():
"""working code"""
The code works perfectly when tested with Postman,
but when I call the axios, I get this line in the server output
127.0.0.1 - - [01/Sep/2018 23:51:12] "POST /designer/api/v1/new_canvas HTTP/1.1" 405 -

Related

How do you remove the "XMLHttpRequest error" in Flutter? (Django backend, Flutter frontend)

I'm having trouble connecting my Django backend to my Flutter frontend on web.I have not tested on Android or iOS yet.
I want to be able to do an API call and have it return a response that I can convert to a json. However it's been throwing errors no matter what I've tried. I've tried converting it into an https request with no avail.
If anyone needs anything on the Django side please let me know
This is what the error looks like:
Error: XMLHttpRequest error.
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 909:28 get current
packages/http/src/browser_client.dart 71:22 <fn>
dart-sdk/lib/async/zone.dart 1613:54 runUnary
dart-sdk/lib/async/future_impl.dart 155:18 handleValue
dart-sdk/lib/async/future_impl.dart 707:44 handleValueCallback
dart-sdk/lib/async/future_impl.dart 736:13 _propagateToListeners
dart-sdk/lib/async/future_impl.dart 533:7 [_complete]
dart-sdk/lib/async/stream_pipe.dart 61:11 _cancelAndValue
dart-sdk/lib/async/stream.dart 1219:7
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 324:14 _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 329:39 dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37307:58
at Object.createErrorWithStack (http://localhost:63593/dart_sdk.js:5362:12)
at Object._rethrow (http://localhost:63593/dart_sdk.js:39509:16)
at async._AsyncCallbackEntry.new.callback (http://localhost:63593/dart_sdk.js:39503:13)
at Object._microtaskLoop (http://localhost:63593/dart_sdk.js:39335:13)
at _startMicrotaskLoop (http://localhost:63593/dart_sdk.js:39341:13)
at http://localhost:63593/dart_sdk.js:34848:9
And this is a code snippet
import 'package:http/http.dart' as http;
var url2 = 'https://0.0.0.0:8809/test/';
try{
response = await http.get(Uri.parse(url2));
print(response.body);
}
catch(exception){
print('could not access');
response = await http.get(Uri.parse(url2));
}
},
I had it print out the error.
It might be caused because CORS is not enabled in your backend. It happens because your server and frontend are present on different IPs (Even if you are doing your work on localhost, the port is still different).
To solve this you you just have to add parameters to enable CORS in your response header. There are packages available for that acts as a middleware so you wont have to add it in every response. Refer the below question :
How can I enable CORS on Django REST Framework

Keycloak Gitpod Flask OIDC: oauth2client.client.FlowExchangeError: Invalid response: 301

I'm trying to implement Flask-OIDC and Keycloak in a Flask app run inside a Gitpod workspace.
I'm running the application and the Keycloak server like this:
./keycloak-11.0.3/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 &
flask run --host=0.0.0.0 &
Based on this post
I'm able to redirect to the Keycloak login page for regular users from within the Flask application, but when I login with an existing user I get the following:
oauth2client.client.FlowExchangeError: Invalid response: 301
My client_secrets.json currently looks something like this:
{
"web": {
"auth_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/protocol/openid-connect/auth",
"issuer": "http://keycloak-hostname-gitpod/auth/realms/realm",
"userinfo_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/protocol/openid-connect/userinfo",
"client_id": "client",
"client_secret": "client_secret",
"redirect_uris": ["http://flask-app-hostname-gitpod/oidc_callback"],
"token_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/protocol/openid-connect/token",
"token_introspection_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/openid-connect/token/introspect"
}
}
Relevant client configuration inside keycloak:
Root URL: http://flask-app-hostname-gitpod/*
Valid Redirect URIs: http://flask-app-hostname-gitpod/*
Admin URL: http://flask-app-hostname-gitpod/*
Web Origins: http://flask-app-hostname-gitpod
I use http in all of these urls instead of https, because when I use https Keycloak says the redirect_uri is invalid. This seems to be the actual problem here since the gitpod urls use https, but I'm not sure how to handle this. I've tried some solutions like described here, but couldn't get them to work.
Relevant part routing:
#app.route("/")
def hello_world():
if oidc.user_loggedin:
return (
'Hello, %s, See private '
'Log out'
) % oidc.user_getfield("preferred_username")
else:
return 'Welcome anonymous, Log in'
#app.route("/private")
#oidc.require_login
def test():
return "test"
Parts of standalone.xml that might be relevant:
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" read-timeout="30000" proxy-address-forwarding="true" />
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true" read-timeout="30000" />
Update
After following changing the http urls to https as Jan Garaj suggested and setting the OVERWRITE_REDIRECT_URI I don't get the invalid response: 301 error anymore:
OVERWRITE_REDIRECT_URI = "https://flask-app-hostname-gitpod/oidc_callback"
Now I'm able to go to the keycloak login form, but on logging in I now get:
oauth2client.client.FlowExchangeError: Invalid response: 401.
These are the requests made:
https://keycloak-hostname-gitpod/auth/realms/realm/login-actions/authenticate?session_code=session_code&execution=execution&client_id=client&tab_id=tab_id
https://flask-app-hostname-gitpod/oidc_callback?state=state&session_state=session_state&code=code
Requests inside the network inspector:
After much trial end error I've finally figured out what the problem was.
The redirect problem in the original question was solved by setting OVERWRITE_REDIRECT_URI:
OVERWRITE_REDIRECT_URI = "https://flask-app-hostname-gitpod/oidc_callback"
The oidc_callback request was still not working however, I was getting this:
oauth2client.client.FlowExchangeError: Invalid response: 401.
Jan Garaj's comment made me realise the problem was that the token endpoint request was not working.
I had checked the token endpoint uri multiple times and copied the value from:
https://flask-app-hostname-gitpod/auth/realms/demo/.well-known/openid-configuration
but it still didn't work.
The reason it didn't work was actually unrelated to my Keycloak configuration, but the way my keycloak server was running inside Gitpod.
Gitpod set the port that the keycloak server was running on to private. Because the keycloak server was running on a private port, the request to the follwing url failed:
https://keycloak-hostname-gitpod/auth/realms/demo/protocol/openid-connect/token
After making the port public it worked.
if you already know that you want a particular port exposed, you can configure it in .gitpod.yml:
ports:
- port: 5000
onOpen: open-preview
- port: 8080
https://www.gitpod.io/docs/config-ports

Django rest framework + axios: Invalid preflight http method on first request

We have a rather strange situation with a react based frontend using axios to talk to our Django rest framework based backend.
When logging in a preflight OPTIONS request is sent by axios (as expected) but the first time the backend receives it, it seems to be malformed and thus results in a 401.
However if I the retry, or even replay the exact same request using the browsers dev tool, the backend accepts the OPTIONS request and everything works as expected. We can consistently reproduce this.
The Django development server log looks like this:
First request
[23/Jan/2019 15:43:42] "{}OPTIONS /backend/api/auth/login/ HTTP/1.1" 401
Subsequent Retry
[23/Jan/2019 15:43:52] "OPTIONS /backend/api/auth/login/ HTTP/1.1" 200 0
[23/Jan/2019 15:43:52] "POST /backend/api/auth/login/ HTTP/1.1" 200 76
So as you can see, curly braces are added in the request method, which means that the request is not considered to be an OPTIONS request, and therefore a 401 is returned.
The django view
class LoginView(KnoxLoginView):
authentication_classes = [BasicAuthentication]
# urls.py (extract)
path('auth/login/', LoginView.as_view(), name='knox_login'),
The Axios request
axios.post('/backend/api/auth/login/', {}, {
headers: {
'Authorization': 'Basic ' + window.btoa(creds.username + ":" + creds.password)
}
}).then((response) => {
dispatch({type: 'SIGNIN_SUCCESS', response})
}).catch((err) => {
dispatch({type: 'SIGNIN_ERROR', err})
})
Some package version info
Django==2.1.4
django-cors-headers==2.4.0
django-debug-toolbar==1.11
django-extensions==2.1.4
django-rest-knox==3.6.0
django-rest-passwordreset==0.9.7
djangorestframework==3.9.0
axios#0.18.0

Vue.js frontend interacting with Flask backend CORS issues due to not allowed preflight headers

I am stuck with the following error message in the Chrome browser:
Failed to load http://localhost:5000/my_endpoint: Request header field
Access-Control-Allow-Origin is not allowed by
Access-Control-Allow-Headers in preflight response.
The browser is loading a webpage from a Vue.js frontend app with webpack etc. and vue-resource to perform HTTP requests to the REST backend.
The URL http://localhost:5000/my_endpoint is a HTTP GET/POST endpoint served by a python Flask application.
On the frontend Javascript I have these CORS settings:
import VueResource from 'vue-resource'
Vue.use(VueResource)
Vue.http.options.crossOrigin = true
Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'
On the backend python code in the Flask app I have the following CORS configuration details:
#app.after_request
def add_header(response):
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Headers'] = 'Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Authorization'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, HEAD'
response.headers['Access-Control-Expose-Headers'] = '*'
return response
When performing this HTTP POST request in the Javascript frontend:
this.$http.post("http://localhost:5000/my_endpoint", { my_custom_key: "my custom value"})//, {emulateJSON: true})
.then((response) => {
// do stuff
})
where { my_custom_key: "my custom value"} is the JSON body of the HTTP POST request, then in the Flask backend for some reason I see an HTTP OPTIONS request coming, cf. the Flask log:
127.0.0.1 - - [26/Jun/2018 21:45:53] "OPTIONS /ad HTTP/1.1" 200 -
There must be some sort of back/forth ceremony to honor before being able to retrieve the JSON data from the backend, but I am lost in these details.
On the internet I've seen all sorts of explanations, and I've been playing a bit with the vue-resource configuration details like:
adding/removing {emulateJSON: true} to the HTTP POST request
adding/removing Vue.http.options.xhr = { withCredentials : true }; to the configuration of Vue.js
but I am not able retrieve the JSON data coming from the backend.
Searching for "CORS" on the Vue.js documentation or on https://github.com/pagekit/vue-resource does not give any information on how to fix these issues with Cross-origin resource sharing (CORS).
How do I get a Vue.js frontend working with a Flask backend on these CORS issues?
The solution was to remove from the frontend: Vue.http.headers.common['Access-Control-Allow-Origin'] = '*' (which actually does not make sense as it's an HTTP header that usually goes into the response from the backend).
Also to clean up a bit more the backend I found out that response.headers['Access-Control-Expose-Headers'] = '*' was not needed. Probably the other HTTP headers could be more slim, but for now I keep them as they are.

Openshift cors request returns 405 method not allowed

I have the following setup on openshift:
one application running wildfly 8 and mysql (A) - sort of a REST api.
one application running a flask app through wsgi (B) - client app.
I want to do a POST request from B to A in order to authenticate. Locally I'm sort of running the same setup, port 8080 for A, 5000 for B and everything works smoothly (of course it does :P), but doing this on openshift I get a 405 response.
Another thing that I've noticed is that if I do the same request from a chrome rest client(Postman) to A the call completes ok, so I'm starting to think that maybe there's something wrong with B, but I can't find anything on the openshift app and again ... locally it behaves as expected.
The flask app uses the requests library. Snippet from login method bellow:
url = API_ROOT + '/login'
payload = {'userId': username, 'password': password}
headers = {'content-type': 'application/json'}
return requests.post(url, verify=False, headers=headers, data=json.dumps(payload))
Thanks.