setting HTTP Header for angularjs REST calls - angularjs

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".

Related

AngularJS get results in error with a 200 response

Angular version is 1.3.13
I'm making a url request to a public url to get some data. For one url it functions but for the other it does not. I have no control over the server side.
The URL returns with 200 but AngularJS passes it to the error function. In my browser console the data is there, as JSON, but I do not have access to it in Angular. I was thinking it might the the http.get calling something before passing the data on.
I've tried with plain $http and a custom transformResponse but it still falls to the error of the custom response.
This is the URL:
https://uatmerchant.sixdots.be/oidc/.well-known/openid-configuration
These are the response headers from the URL:
Connection
close
Content-Security-Policy
reflected-xss block
Content-Type
application/json
Date
Mon, 15 Jan 2018 12:33:30 GMT
Set-Cookie
BIGipServer~DMZ~pool_uat_5000=…omain=.uatmerchant.sixdots.be
Strict-Transport-Security
max-age=15552000; includeSubDomains
Transfer-Encoding
chunked
X_CORRELATION_ID
UAT-MER-F5-20180115133330632
X-Content-Security-Policy
reflected-xss block
X-Content-Type-Options
nosniff
X-Frame-Options
SAMEORIGIN
X-Xss-Protection
1; mode=block
This is part of the data that is in the response in the browser console
request_parameter_supported true
claims_parameter_supported false
scopes_supported […]
0 openid
1 profile
2 email
3 address
4 phone
issuer https://uatmerchant.sixdots.be/oidc
acr_values_supported […]
0 tag:sixdots.be,2016-06:acr_basic
Here is the code making the call with the URL that is detailed at the start of this post above
var oohahhel = $sce.trustAsResourceUrl(urlVar);
$http.get(oohahhel)
.then(
function success(response){
var jsonResponse = angular.fromJson(response);
//process response
}
,function error(reason){
//process error
});

CORS issue with angular $http.post - successful requests result in errors with status 0

I'm using angular to POST to an authentication endpoint; on the server side, I can see the request succeed, and proper CORS headers are set. Angular's origin is http://localhost:9000
On the server side, preflight OPTIONS requests always get a 200 back, so that seems OK.
On the client side, the $http.post always fails with an error code of 0, which from other research suggests something is still wrong with CORS. I've read the spec and tried a number of other answers, yet something is still missing.
Angular POSTs like this:
$http({
method: 'POST',
url: 'http://localhost:3000/auth/login',
data: {
username: $scope.username,
password: $scope.password
}
})
.then(function (response) {
/* etc. etc. */
}, function (response) {
/* This always triggers, with response.status = 0 */
console.log("ERROR: " + response.data);
console.log("Status: " + response.status);
console.log("Status text: " + response.statusText);
console.log("Headers: " + response.headers);
$scope.error = 'Something went wrong...';
});
Using curl to debug what the server is sending back, this is it:
< HTTP/1.1 302 Found
< X-Powered-By: Express
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS
< Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, Content-Length, X-Requested-With
< Access-Control-Allow-Credentials: true
< Set-Cookie: ua_session_token=(blahblah); Path=/
< Location: /
< Vary: Accept
< Content-Type: text/plain; charset=utf-8
< Content-Length: 23
< Date: Mon, 28 Dec 2015 15:08:17 GMT
< Connection: keep-alive
This is why I'm at a loss, as per the specification, the server seems to be doing the right thing?
Here's what the server gets from the client in terms of request headers:
HEADER host localhost:3000
HEADER content-type application/json;charset=UTF-8
HEADER origin http://localhost:9000
HEADER content-length 38
HEADER connection keep-alive
HEADER accept application/json, text/plain, */*
HEADER user-agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9
HEADER referer http://localhost:9000/
HEADER accept-language en-us
HEADER accept-encoding gzip, deflate
UPDATE tried something else with no luck, based on this post. It would seem Access-Control-Allow-Headers is case-sensitive, and angular is sending on the request accept, origin, content-type. I tweaked the server to parrot back the same, with no luck.
Alright, after applying my head to my keyboard for several hours, I've fixed it.
The answer seems to be that angular really doesn't like getting redirects in response to POST. When I changed the server endpoint to return just a plain auth token as text (the same token it was setting as a cookie anyway) rather than returning a redirect, the angular POST started working like a charm and falling through to the success handler.
Not sure I got deep enough into this to know why angular was behaving in that way; by playing around with it I found that if the redirect the server sent was to a nonexistent (404) URL that this could be replicated, EVEN IF the original POST returned that valid redirect.

Angularjs $http.post() is sending an OPTIONS request only

I've got some Angular code where I am attempting to send a POST to a dev server.
var url = 'http://someDevUrl.com',
data = { 'someKey': 'some value' };
$http.post(url, data);
It sends the OPTIONS preflight request. I can see it hit the server, and the server gives it a happy response.
OPTIONS Response Headers:
HTTP/1.1 200 OK
Server: Cowboy
Date: Mon, 08 Dec 2014 18:20:44 GMT
Connection: close
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 30
Access-Control-Allow-Headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Via: 1.1 vegur
but then Angular never sends the POST after that...
Typically when $http.post() only sends an OPTIONS request, that means the OPTIONS request returned an error (usually a CORS issue). But in this case, all is fine with the OPTIONS request & response, but it still won't send the POST.
Has anyone seen this before or have an idea of what might be preventing it from sending the POST?
EDIT:
I've got around the issue by adding a Content-Type: text/plain header to the request:
var url = 'http://someDevUrl.com',
data = { 'someKey': 'some value' },
config = {
headers: {
'Content-Type': 'text/plain'
}
}
};
$http.post(url, data, config);
which causes it to skip the OPTIONS preflight, thus avoiding the issue. I'm still curious to know why it was not working in the first place, since there was/is no CORS issue and the OPTIONS request was not sending back an error response.

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!

CORS - CakePHP does not accept AngularJS JSON-Request

I'm using CakePHP as backend and AngularJS as frontend, whereas front- & backend are in different domains so this is basically a CORS-situation.
Basically I'm trying to send the contents of a form to a Cake-API (later this is meant to do authentication part - but I'm failing earlier) via $http.post. So here is the code:
aeapBackend.login = function(username, password) {
return $http.post(
API_URL + 'api_mobile_user/login', {
test: username,
test2: password
}
);
};
Whereas the corresponding API in CakePHP looks like this:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array('login'));
}
public function login() {
$this->response->header(array(
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Headers' => 'Content-Type'
)
);
$this->autoRender = false;
}
What happens next is that the preflight OPTIONS request ist done - which looks quite good to me:
Request Headers:
OPTIONS /api_mobile_user/login HTTP/1.1
Host: aeap.localhost
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://asf.localhost
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53
Access-Control-Request-Headers: accept, content-type
Accept: */*
Referer: http://asf.localhost/?username_input=hjk&password_input=hjgk&login_button=
Accept-Encoding: gzip,deflate,sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Response headers:
HTTP/1.1 200 OK
Date: Wed, 05 Nov 2014 15:29:00 GMT
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15
X-Powered-By: PHP/5.5.15
Set-Cookie: CAKEPHP=j6st0hnq8ear2cc6psg56d6eu3; expires=Wed, 05-Nov-2014 19:29:00 GMT; Max-Age=14400; path=/; HttpOnly
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
But when the actual POST-request is done I get an status code 403:
XMLHttpRequest cannot load http://aeap.localhost/api_mobile_user/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://asf.localhost' is therefore not allowed access. The response had HTTP status code 403.
How can I avoid this? In my opinion I already enabled CORS support for Cake ['Access-Control-Allow-Origin']. It seems to me that AngularJS posts some additional informations whioch are not checked during the preflight and then rejected by the backend.
Used versions: CakePHP 2.5.3, AngularJS: 1.3.0
Thanks to Marvin Smit I was able to determine the reason for the behavior which was not connected to CORS are the headers. I set 'Access-Control-Allow-Origin' => '*'on web-server level so I was able to get a response which pointed to the security component of CakePHP.
I basically tried to send a POST-Reuqest to an API which did not expect that data should be posted to it. Therefore the access was denied. So I had to add $this->Security->csrfCheck = false to the beforeFilter:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array('login'));
$this->Security->csrfCheck = false;
}
For what it's worth, the proper way to do this for Cakephp 3 is as follows
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array('login'));
$this->eventManager()->off($this->Csrf);
}
Although, this is not recommended for AJAX requests. The following doc can help you more. CSRF And AJAX

Resources