Angular app sends just option request without post [duplicate] - javascript

This question already has answers here:
How does the 'Access-Control-Allow-Origin' header work?
(19 answers)
Closed 3 years ago.
I'm making an app in angular 7 that connects to API that I wrote in python. I want to send a text in POST request and API does some nlp stuff and returns the result. API is using RestPlus and is hosted on GCP App Engine. So in angular I have this code:
posts: any;
readonly ROOT_URL = 'XXX';
const httpOptions = {
headers: new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
'X-API-KEY': 'X',
})
};
const data: any = {
"article": this.text
};
this.posts = this.http.post(this.ROOT_URL, data, httpOptions);
this.text is a value I get from form and I've already checked if it's valid. X-API-KEY is a token I set in API.
In console I get:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at XXX. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at XXX. (Reason: CORS request did not succeed).
I tried sending a post request to postb.in to test it and got the same errors. And postb.in shows that it only received OPTION requests.

Cross origin request means that you are trying to make an API call to a server which is not your origin (this server is not rendering the front-end/client-end).
Example: If http://localhost/dummy-app delivers the front-end and you are trying to make an API call from this front-end to http://localhost:3000/dummy-api, it will result in a CORS issue.
Resolutions:
Render the front-end from the server where the API end point exists. This is only a technical solution and may not be a good architecture or not even possible at times.
Allow CORS in server. (Not highly recommended)
Use a middleware server to render your front end. This server can have an API endpoint through which you can pass the request to desired API. CORS issue appears to be a blocking by the browser and appears only when an external API is called from front-end. You can call an API in the middleware server which then further calls the external API.
Recommended : Use your web server to do the job. For example, create a new route in Nginx which proxy passes your request to the API.
location /api{
proxy_pass http://localhost:3000
}
In this method http://localhost/dummy-app can call the API as http://localhost/api/dummy-api.

Related

How to force authentication in preflight request?

I'm trying to call Github REST API from client-side javascript (in browser).
My code does the following (I'm trying to get a zip containing the branch mkdocs_page of a private repository) :
const endpoint = 'https://api.github.com';
const resource = '/repos/astariul/private-gh-pages/zipball/mkdocs_page';
const options = {
mode: 'cors',
headers: {
'Authorization': 'Basic ' + btoa(`${pat}`), // pat contains my Personal Access Token
}
}
return fetch(`${endpoint}${resource}`, options);
But it does not work :
The preflight request fails with 404.
The console error message :
Access to fetch at 'https://api.github.com/repos/astariul/private-gh-pages/zipball/mkdocs_page' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
In the process of debugging this, I tried to reproduce the problem with curl. And when I specify an authenticated request, it works :
curl --user "<my_PAT_token>" -i https://api.github.com/repos/astariul/private-gh-pages/zipball/mkdocs_page -X OPTIONS
HTTP/1.1 204 No Content
But if the request is not authenticated, it does not work :
curl -i https://api.github.com/repos/astariul/private-gh-pages/zipball/mkdocs_page -X OPTIONS
HTTP/1.1 404 Not Found
Note : it works fine when I'm trying to get the master branch (authenticated or not). However it fails after, when being redirected :
Access to fetch at 'https://codeload.github.com/astariul/private-gh-pages/legacy.zip/refs/heads/main?token=XXX' (redirected from 'https://api.github.com/repos/astariul/private-gh-pages/zipball') from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Is it a bug in the Github API ? Or I'm doing something wrong ?
There’s no way to force authentication in a preflight request. The preflight is controlled totally by the browser, and nothing about it is exposed in any way that you can manipulate from frontend JavaScript code. And the requirements for the CORS protocol explicitly prohibit browsers from including any credentials in preflight requests.
For a detailed explanation, see the answer at https://stackoverflow.com/a/45406085/.
Since the preflight involves the browser making an OPTIONS request, then in general, if a server requires authentication for OPTIONS request to a particular resource (which seems to be the case for the GitHub URL cited in the question) that’s not at all necessarily an unintended bug.
That’s because the only normal case in which a preflight is performed and an OPTIONS request is sent is for the case of frontend JavaScript code running in a browser. Requests made from server-side code or from code running in shell/command-line environment or from desktop apps or native mobile apps don’t involve sending an OPTIONS request.
So, lack of support for unauthenticated OPTIONS requests to a particular resource would only be a bug if the provider actually intended it to be used from frontend code running in a browser. In other words, it can instead indicate the provider intentionally doesn’t want it to be used from frontend JavaScript code (which seems to be the case for the URL cited in the question).

How to add Cross Origin Resource Sharing request headers? [duplicate]

This question already has answers here:
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 4 years ago.
I am building a REST-consumer using React JS, I have build a REST api as the backend service the frontend will be a completly different application. To sepparate the frontend from the backend.
What I am currently struggling with is making a cross origin request from the frontend to the backend. The backend is hosted at http://localhost:8080 and the frontend react app is hosted at http://localhost:3000. When making a request I get the following error on the console:
Failed to load http://localhost:8080/api/something: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Right now I have fixed this error with a chrome extension to allow CORS: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en
But this is just a temporary sollution, I have tried adding the Access-Control-Allow-Origin header but that does not seem to work.
This my code used to make the request:
let Myheaders = new Headers()
Myheaders.append("Access-Control-Allow-Origin", "http://localhost:8080/")
let res = await fetch("http://localhost:8080/api/something",
{
method: "get",
mode: "cors",
headers: Myheaders
})
let res1 = await res.json()
I have tried adding multiple values for the Access-Control-Allow-Origin header with backslash or without backslash, but nothing seems to work.
Anyone run into the same issues and have a sollution for it?
this is a backend issue not a frontend
you should allow the cors from the backend and this is depend on the technology that used in the backend

ReactJS API Data Fetching CORS error

I've been trying to create a react web app for a few days now for my internship and I've encountered a CORS error. I am using the latest version of reactJS, and placing this in the create-react-app, and below is the code for fetching:
componentDidMount() {
fetch('--------------------------------------------',{
method: "GET",
headers: {
"access-control-allow-origin" : "*",
"Content-type": "application/json; charset=UTF-8"
}})
.then(results => results.json())
.then(info => {
const results = info.data.map(x => {
return {
id: x.id,
slug: x.slug,
name: x.name,
address_1: x.address_1,
address_2: x.address_2,
city: x.city,
state: x.state,
postal_code: x.postal_code,
country_code: x.country_code,
phone_number: x.phone_number,
}
})
this.setState({warehouses: results, lastPage: info.last_page});
})
.then(console.log(this.state.warehouses))
}
I'm sorry that I can't post the url for the API due to company rules, however, it is confirmed that there are no CORS setting in the API backend.
However, I encounter the following errors when run on mozilla
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ------------------. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
and
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ---------------------------------------------. (Reason: CORS request did not succeed).
If run on chrome it gives the following error
Failed to load resource: the server responded with a status of 405 (Method Not Allowed)
and
Failed to load --------------------------------------------------------: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 405. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
and
Uncaught (in promise) TypeError: Failed to fetch
Another thing is that I am able to open the url in my browsers with no problems or whatsoever.
Please help and thanks!
Additional Information
The reason I added the CORS setting is because it gives a CORS error, so removing it does not really solve the issue.
Next I tried to perform proxy setting, however, it now gives
Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0
According to the internet this is caused becasue the response is not a JSON. However when I checked the API it gives this
api img
which means that return type should be a JSON right?
Additional Info
checking the respond will yield this
{"status":200,"total":1,"per_page":3,"current_page":1,"last_page":1,"next_page_url":null,"prev_page_url":null,"from":1,"to":3,"data":[{"id":1,"slug":"america","name":"america","address_1":"USA Court","address_2":"USA","city":"USA","state":"USA","postal_code":"94545","country_code":"US","phone_number":"10000001","created_by":null,"updated_by":null,"created_at":"2017-11-10 11:30:50+00","updated_at":"2018-06-28 07:27:55+00"}]}
The CORS settings need to be setup in the API to allow access from your React app domain. No CORS settings, no AJAX from different domains. It's simple as that. You can either add CORS settings to your company API (this is unlikely to happen) or you can work around like described below:
The CORS is solely a mechanism of client browser to protect users from malicious AJAX. So one way to work around this is proxying your AJAX request from your React app to its own web server. As Vincent suggests, the create-react-app provides an easy way to do this: in your package.json file, simply chuck "proxy": "http://your-company-api-domain". For more details, please see this link
Then in your react app you can using relative URL like this: fetch('/api/endpoints'). Notice that the relative URL has to match with your company API. This will send a request to your server, then the server will forward the request to your company API and return the response back to your app. Since the request is handled in the server-to-server way not browser-to-server so the CORS check won't happen. Therefore, you can get rid of all unnecessary CORS headers in your request.
This is what I did using vite
Package.json file add:
"proxy": "http://api_website_where_the_request_is_comming/",
App component or whatever component you making the call do this
let endpoint = /api/your_endpoint/;
fetch(endpoint).then(function (response) {
return response.json()
})
.then(function (jsonData){
console.log('Banner log', jsonData);
})
In your backend, make sure that the app is use cors.
Run this to install cors
npm install cors --save
Import cors in the app using
const cors = require('cors');
app.use(cors()) // if name of your backend is app

Trying to make a JSON POST request to the TVDB REST API at https://api.thetvdb.com/, but getting CORS error

I am porting an application from Django to purely HTML5/CSS with AngularJS and am facing issues making JSON POST requests to TheTVDB REST API server (https://api.thetvdb.com/).
The API call is being done in a service on AngularJS:
return {
login: function(){
return $http({
method: 'POST',
dataType: 'json',
headers: {'Content-Type': 'application/json'},
data: {'apikey':apiKey, 'username': username, 'userkey': identifier},
url: tvdbAuthURL
})
}
}
And then I get this error:
XMLHttpRequest cannot load https://api.thetvdb.com/login/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 401.
I have tried avoiding pre-flighting the request but no luck and since I did not have this issue using python requests lib, for example, (I trigger request to the tvDB using this python lib from the same machine running the angular JS app with no problems at all) I wonder if there isn't a way or a different directive in AngularJS to keep it from setting CORS headers.
TheTVDB will not add CORS to their server as most of their users are running Laravel (PHP), Java and Django(Python) applications and are using their services with no such CORS problems.
Your help is much appreciated.
Thank you,
Best Regards
TS
You can have a look here: https://forums.thetvdb.com/viewtopic.php?t=9125
The TVdb doesn't provide any cors header, which means you can't access the API directly via Javascript. However, as #Matt West said, the cors policy only works in browsers.
The quick solution: Create a python program as a proxy, which redirect all your AJAX request to TVdb.
Your Python request works because it is coming from your server or local machine, and the same origin policy only applies inside a browser.
Your best answer is to use a server-side script. Have your client side POST request go to a controller or endpoint on your server, which then triggers the server script. Assuming there is some return data from the API, you'd add that to your server's response and then send it to the client.
Use a JSONP request. That way you can dodge the CORS.
EDIT: sorry, you're using POST, this would only work for get requests.
You can create a proxy that receives the request and then makes a CURL POST. There is no server side 'CORS' so you will be ok.

AngularJS No 'Access-Control-Allow-Origin' header [duplicate]

This question already has answers here:
“Origin null is not allowed by Access-Control-Allow-Origin” error for request made by application running from a file:// URL
(17 answers)
Closed 6 years ago.
I have an AngularJS app that I need to post data to a third party URL which is used to store some data on the third party server. I get the following error when I run my code below:
XMLHttpRequest cannot load http://thirdparty.url.com/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:51491' is therefore not allowed access.
The code I'm running in my AngularJS factory is:
return $http({
url: '//thirdparty.url.com',
method: "POST",
data: params_string,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT',
'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
}
});
Cross-Origin Resource sharing(CORS) is a specification that defines the ways for a web server to allow its resources to be accessed by the script running in a web page from a different domain.
The Server and the client work together, using HTTP headers to make accessing cross origin resources possible.
In your case since you browser(client) is chrome/Firefox(and not the older version of IE) , the problem is not with browser.
When you make an ajax call , browser by default will add a request header
Origin: yourdomainname
Your ajax call will only be successful when the server(http://thirdparty.url.com) sends a response similar to below
Access-Control-Allow-Origin: *
In your case , the above response header is not being sent by server.
This means that your http://thirdparty.url.com/
Does not accept requests from external sources that is/are not from http://thirdparty.url.com/, so you have to enable it from your thirdparty.url.com
Access-Control-Allow-Origin header needs to be added in the thirdparty.url.com that you are trying to access and not in your own code. It is for the website to control allowing access to the users, So you can do anything about it from your side.
Add the extension CORS
to your chrome browser.
You can't enable CORS from client side.
I should set at server level.
HTTP access control (CORS)

Categories