angularJS $http.Post not working: Failed to load resource: Request header field 0 is not allowed by Access-Control-Allow-Headers - angularjs

I'm using $http to post some data to my data base.
Here is the documentation of the database.
I use it on my terminal and it works.
Here's the error message I got from Safari's console:
1)Failed to load resource: Request header field 0 is not allowed by Access-Control-Allow-Headers. (seems to be sensed by the database)
2)XMLHttpRequest cannot load https://beta-api.mongohq.com/mongo/MyDId/myDatabse/collections/myCollection/documents. Request header field 0 is not allowed by Access-Control-Allow-Headers.
Here's my code:
factory.sendUrlTag = function(data){
d = '{"document" : {"url_URL":"53738eef9256a31f4fdf6bf8","tag_Tag":"537375fc9256a31f4fdf6bf3"} }'
return $http({
url: 'https://beta-api.mongohq.com/mongo/MyDId/myDatabse/collections/myCollection/documents',
method: "POST",
data: d,
headers: [
{'Access-Control-Allow-Origin':'*'},
{'Access-Control-Allow-Headers':'Origin, X-Requested-With, Content-Type, Accept'},
{'Content-Type': 'application/json'},
{'Authorization' : 'api-key MyKey'}
]
})
}
return factory;
};
I didn't have " {'Access-Control-Allow-Origin':'*'},
{'Access-Control-Allow-Headers':'Origin, X-Requested-With, Content-Type, Accept'}," before, but I did some research after I got the error and added these. But it's still not working.
I do $http.get() in my app to the same database and it works.
This thing is driving me nuts....
Please help!
Thank you all! :)

Access-Control-Allow-Origin and friends are response headers, not request headers. It wouldn't make sense if Bob was responsible for granting Bob permission to Alice's system.
The server (https://beta-api.mongohq.com/mongo/MyDId/myDatabse/collections/myCollection/documents) has to send them, not the client.
Since you are making a cross-origin POST request, the server also needs to be able to respond to a pre-flight OPTIONS request.

I found some way maybe able to get around the issue:
Use this and here to get around the cross origin origin issue.
And this to get around the localhost
It may work.
Another relative post.

Related

Angular $http.post returns 404 error

I am using angular JS to send some data to Payment Gateway.
Syntax for curl to send data as per documentation is:
curl https://www.mybank.co.uk/3dsecure
-H "Content-type: application/x-www-form-urlencoded"
-X POST
-d 'TermUrl=https://www.yourmerchantsite.co.uk/3DSecureConfirmation&PaReq=value-of-oneTime3DsToken&MD=merchantdatavalue'
However when I am doing it in Angular :
$http({
method: 'POST',
url: 'url',
headers: {'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'text/html'
},
data: $.param({TermUrl: obj.TermUrl ,Pareq: obj.Pareq }),
})
I am getting error
Possibly unhandled rejection: {"data":"<html><head><title>400 Bad
Request</title></head><body><h1>Bad Request</h1></body>
</html>","status":400,"config":
{"method":"POST","transformRequest":[null],"transformResponse":
[null],"jsonpCallbackParam":"callback","url":"payement gatway
url","headers":{"Content-Type":"application/x-www-form-urlencoded",
"Accept":"text/html,application/xhtml+xml"},"data":"TermUrl=url&Pare
q=value"},"statusText":"Bad Request","xhrStatus":"complete"}
Kindly suggest how to proceed with this one ?
First of all, you are experiencing a 400 Bad Request (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400) and not a 404 Not Found.
It usually means that you are not sending the right data to the server and the API is expecting some specific parameters (from the body usually).
Check the API, look at every parameter required from it - their types and how they should be sent (body param? query string? etc...).
You can use your browser network tab or tools like Postman to see what you are actually sending to the server and if it matches what the server is expecting you to send.
Check out 3D Secure's API reference, you should get back a detailed error code beside the http status code:
https://developer.paysafe.com/en/3d-secure/api/#/introduction/error-summary/common-errors
It should be easily debuggable.

Google drive api invalid client

I am trying to get access to the google drive content of my users.
I can redeem a code on my domain using the google drive user consent url with correct parameters:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id='+$scope.googledriveApi.client_id+'&scope='+$scope.googledriveApi.scopes+'&redirect_uri='+$scope.googledriveApi.redirect_uri
I am trying to do an angular $http request to the https://www.googleapis.com/oauth2/v4/token endpoint.
The request looks like this:
$http({
method: 'POST',
headers: {"Content-Type" : "application/x-www-form-urlencoded"},
data: $.param({
"code" : $routeParams.code,
"client_id" : $scope.googledriveApi.client_id,
"client_secret" : $scope.googledriveApi.secret,
"redirect_uri" : $scope.googledriveApi.redirect_uri,
"grant_type" : "authorization_code"
}),
url: 'https://www.googleapis.com/oauth2/v4/token'
})
However the response I get from the request is as follows:
{
"error": "invalid_client",
"error_description": "The OAuth client was not found."
}
Does anyone know why this happens? I have tried changing product name and client id name to be the same. I have checked this for spaces. The reason I'm mentioning this is because this seemed to be the case for other people who asked a question for the same error, however my error happens at the $http request.
I am getting back the user consent code and I am trying to exchange for an access token in this request. This is when the error comes in and I am stuck.
Try these:
Under OAuth consent screen, make sure Product name is not the same with project name as stated in this SO thread:
Try to include an authorization header in your URI request:
headers: { 'Authorization': 'bearer ' + accessToken }

How to post JSON data to REST Webservice in AngularJS

How to post JSON data to web-service via AngularJS
here is the code snippet
.controller('MessagePostCtrl', function($scope, $http) {
$scope.postMessage = function() {
var msg = document.getElementById('message').value;
var msgdata = {
message : msg
};
var res = $http.post('http://<domain-name>/messenger/api/posts/savePost',msgdata);
res.success(function(data, status, headers, config) {
console.log(data);
});
}
})
OPTIONS http:///messenger/api/posts/savePost
ionic.bundle.js:16185(anonymous function) ionic.bundle.js:16185
sendReq ionic.bundle.js:15979 serverRequest ionic.bundle.js:15712
wrappedCallback ionic.bundle.js:19197 wrappedCallback
ionic.bundle.js:19197(anonymous function) ionic.bundle.js:19283
Scope.$eval ionic.bundle.js:20326 Scope.$digest ionic.bundle.js:20138
Scope.$apply ionic.bundle.js:20430(anonymous function)
ionic.bundle.js:43025(anonymous function) ionic.bundle.js:10478
forEach ionic.bundle.js:7950 eventHandler ionic.bundle.js:10477
triggerMouseEvent ionic.bundle.js:2648 tapClick ionic.bundle.js:2637
tapMouseUp ionic.bundle.js:2707
XMLHttpRequest cannot load
http:///messenger/api/posts/savePost. Invalid HTTP
status code 404
But when I remove the msgdata from $http.post method, everything is working fine.
Can anyone tell me where the issue is or else guide me how to send JSON data to web-service
Thanks for the help
**Edited:
The Issue was with the CORS, Im using codeigniter REST Controller for web-services.
Modified the headers. If anyone has the same issue add the below header in the construct
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method");
if ( "OPTIONS" === $_SERVER['REQUEST_METHOD'] ) {
die();
}
Thanks to Linial for the break-through, telling me where the issue is.**
Okay,
You mixed up couple of things:
First as I can see your request has changed from POST to OPTIONS.
Why?
You are performing Cross-site HTTP requests ( CORS ), which means that your WebApp and your backend API are not in the same domain.
What happens live is that the request is being preflighted.
Preflighted request: by Mozilla MDN:
It uses methods other than GET, HEAD or POST. Also, if POST is used
to send request data with a Content-Type other than
application/x-www-form-urlencoded, multipart/form-data, or text/plain,
e.g. if the POST request sends an XML payload to the server using
application/xml or text/xml, then the request is preflighted.
Which means, any request beside GET, HEAD or POST will be change to OPTIONS
AND: Also POST if used to send data with Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain
I now understand, but what to do? I have to make POST request!
You don't have many options, since CORS is defined on the server.
But on the client you could do so (Example):
change the encode type in angular like so:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
OR
Set your server to approve CORS like so:
Access-Control-Allow-Headers: Content-Type \\ This will allow you to set content type header in the client.
Access-Control-Allow-Methods: GET, POST, OPTIONS \\ This will allow you to send GET POST and OPTIONS, which is necessary because of preflighted requests.
Access-Control-Allow-Origin: * \\ This will allow anyone to perform CORS requests.
Good Luck!

setting HTTP Header for angularjs REST calls

I'm trying to set a HTTP Header for all my REST calls with following code:
app.factory('authInterceptor', function ($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
config.headers.Authorization = '12345678';
return config;
},
response: function (response) {
if (response.status === 401) {
// handle the case where the user is not authenticated
}
return response || $q.when(response);
}
};
});
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
I currently don't have any authorization enabled on the server.
when I leave out the line "config.headers.Authorization = '12345678';" , then the REST call works well and I get my results. In the JS console I see
GET http://localhost:8080/rest/club/1 [HTTP/1.1 200 OK 7ms]
But when I put this line in to set the Header field, then I see following request in the javascript console
OPTIONS http://localhost:8080/rest/club/1 [HTTP/1.1 200 OK 2ms]
Why does setting Authorization Header change my method from "GET" to "OPTIONS"? And how can I set a custom Header and my request still work?
changing it to
config.headers["X-Testing"] = '12345678';
had the same result.
EDIT:
I tried the answer, I'm setting following HTTP Headers in the server:
response.getHeaders().putSingle("Access-Control-Allow-Origin", "http://localhost");
response.getHeaders().putSingle("Access-Control-Allow-Header", "X-Testing");
response.getHeaders().putSingle("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.getHeaders().putSingle("Access-Control-Max-Age", 1728000);
my REST server is running on port 8080, the webserver for the html/JS on port 8000 (initially worked with file://... but moved to a separate webserver because Origin was null)
response.getHeaders().putSingle("Access-Control-Allow-Origin", "*");
or
response.getHeaders().putSingle("Access-Control-Allow-Origin", "http://localhost:8000");
didn't work either.
Must I return any content in the OPTIONS response? I tried 200 OK with the same content as the GET, but I also tried 204 No Content.
2nd EDIT:
here is what firefox sends and receives for the OPTIONS method:
You need to enable CORS in your REST service. As explained in MDN, once you add a custom header, the http protocol specifies performing a preflight,
Preflighted requests
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used
to send request data with a Content-Type other than
application/x-www-form-urlencoded, multipart/form-data, or text/plain,
e.g. if the POST request sends an XML payload to the server using
application/xml or text/xml, then the request is preflighted. It sets
custom headers in the request (e.g. the request uses a header such as
X-PINGOTHER)
Addition to enabling CORS you also need to add a Access-Control-Allow-Headers header tag to accept your custom header (for the OPTIONS response). This is visible in the MDN Example,
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
Access-Control-Max-Age: 1728000
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
UPDATE
As mentioned in the comments, the OPTION response's Access-Control-Allow-Headers is missing the last "s".

NetworkError: 405 Method Not Allowed AngularJS REST

In AngularJS, I had the following function, which worked fine:
$http.get( "fruits.json" ).success( $scope.handleLoaded );
Now I would like to change this from a file to a url (that returns json using some sweet Laravel 4):
$http.get( "http://localhost/fruitapp/fruits").success( $scope.handleLoaded );
The error I get is:
"NetworkError: 405 Method Not Allowed - http://localhost/fruitapp/fruits"
What's the problem? Is it because fruit.json was "local" and localhost is not?
From w3:
10.4.6 405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource
identified by the Request-URI. The response MUST include an Allow header
containing a list of valid methods for the requested resource.
It means the for the URL: http://localhost/fruitapp/fruits The server is responding that the GET method isn't allowed. Is it a POST or PUT?
The angular js version you are using would be <= 1.2.9.
If Yes, try this.
return $http({
url: 'http://localhost/fruitapp/fruits',
method: "GET",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
I had a similar issue with my SpringBoot project, I was getting the same error in the browser console but I saw a different error message when I looked at the back-end log, It was throwing this error: "org.springframework.web.HttpRequestMethodNotSupportedException, message=Request method 'DELETE' not supported " It turned out that I was missing the {id} parameter in the back-end controller:
** Wrong code :**
#RequestMapping(value="books",method=RequestMethod.DELETE)
public Book delete(#PathVariable long id){
Book deletedBook = bookRepository.findOne(id);
bookRepository.delete(id);
return deletedBook;
}
** Correct code :**
#RequestMapping(value="books/{id}",method=RequestMethod.DELETE)
public Book delete(#PathVariable long id){
Book deletedBook = bookRepository.findOne(id);
bookRepository.delete(id);
return deletedBook;
}
For me, it was the server not being configured for CORS.
Here is how I did it on Azure: CORS enabling on Azure
I hope something similar works with your server, too.
I also found a proposal how to configure CORS on the web.config, but no guarantee: configure CORS in the web.config. In general, there is a preflight request to your server, and if you did a cross-origin request (that is from another url than your server has), you need to allow all origins on your server (Access-Control-Allow-Origin *).

Resources