I am using NGINX and sparkjava for my web application. I am sure I have enabled all CORS headers properly. Still, I am getting "XMLHttpRequest cannot load http://localhost:3003/platformAPI/login. Invalid HTTP status code 404" error.Below mentioned are my client and server methods from extjs and spark java respectively. I have inspected the network tab of my browser to get the response and request headers sent as well. They are also mentioned below. Any help to let me know as to what's wrong with my approach is highly appreciated :)
Client method from Nginx:
function(button, event, options){
var form = Ext.getCmp("LoginformId").getForm();
if (form.isValid()) {
var userJson = JSON.stringify(form.getFieldValues());
form.submit({
url: 'http://localhost:3003/platformAPI/login',
//headers : {'Content-Type':undefined,},
//dataType: 'jsonp',
success: function(form, action) {
// Ext.Msg.alert('Success', action.result.msg);
var sessionID=action.result.sessionID;
var clientName=action.result.clientName;
sessionStorage.setItem('sessionID',sessionID);
sessionStorage.setItem('clientName',clientName);
window.location="http://localhost:3000/";
},
failure: function(form, action) {
Ext.Msg.alert('Failed', action.result.msg);
}
});
}
}
Server Methods:
filter to enable CORS headers (Calling this in main)
private static void enableCORS(final String origin, final String methods, final String headers) {
before(new Filter() {
#Override
public void handle(Request request, Response response) {
response.header("Access-Control-Allow-Origin",request.headers("origin"));
response.header("Access-Control-Allow-Headers", "Origin, x-requested-with, content-type, Accept");
response.header("Access-Control-Request-Method", "GET,PUT,POST,DELETE,OPTIONS");
);
}
});
}
Login method:
post("platformAPI/login", "undefined",
(request, response) -> {
System.out.print("inside login");
JSONObject object1 = new JSONObject();
response.body(object1.put("success", true).toString());
return response;
});
Request and response headers:
Remote Address:127.0.0.1:3003
Request URL:http://localhost:3003/platformAPI/login
Request Method:OPTIONS
Status Code:404 Not Found
Response Headers
view source
Access-Control-Allow-Headers:Origin, x-requested-with, content-type, Accept
Access-Control-Allow-Origin:http://localhost:3000
Access-Control-Request-Method:GET,PUT,POST,DELETE,OPTIONS
Cache-Control:must-revalidate,no-cache,no-store
Content-Length:295
Content-Type:text/html; charset=ISO-8859-1
Server:Jetty(9.0.2.v20130417)
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:x-requested-with, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:3003
Origin:http://localhost:3000
Referer:http://localhost:3000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Try enable CORS in Spark-Java with the following snippet:
options("/*",
(request, response) -> {
String accessControlRequestHeaders = request
.headers("Access-Control-Request-Headers");
if (accessControlRequestHeaders != null) {
response.header("Access-Control-Allow-Headers",
accessControlRequestHeaders);
}
String accessControlRequestMethod = request
.headers("Access-Control-Request-Method");
if (accessControlRequestMethod != null) {
response.header("Access-Control-Allow-Methods",
accessControlRequestMethod);
}
return "OK";
});
before((request, response) -> {
response.header("Access-Control-Allow-Origin", "*");
});
Provided you must consider this point as well.
It will works with Postman because you are directly calling the server. There is no CORS involved here. But when you do it through javascript or angular etc.. CORS comes into play. So the requested url doesn't contain http scheme. You need to change localhost:portNumber/login to http://localhost:portNumber/login
Related
All, I just created a new Angular package using 1.6.1 but now the data doesn't seem to pass to my WebAPI. However, when I post bits via SoapUI or something like that, everything is fine.
The Javascript looks like this:
function testapi()
{
var serviceRoot='http://server/testangular16/api/Values';
var deferred=$q.defer();
var req = {
method: 'POST',
url: serviceRoot,
data: 'PassInTheText'
};
$http(req).then(goodResponse,badResponse);
return deferred.promise;
};
function goodResponse(response)
{
console.log("Good response");
console.log(response);
}
function badResponse(response)
{
console.log("Bad response");
console.log(response);
}
and the webapi is a very simple C# controller:
// POST api/values
public HttpResponseMessage Post([FromBody]string value)
{
HttpResponseMessage rp = new HttpResponseMessage(HttpStatusCode.OK);
rp.Content = new StringContent(value);
return rp;
}
I am making it into the controller, I can set a break point and hit the parts where I can look at the value. It's always null.
Looking at the network trace, the angular part does do a preflight and I can see the 200 response back.
Request URL:http://server/testangular16/api/Values
Request Method:OPTIONS
Status Code:200 OK
Remote Address:10.7.14.209:80
**Response Headers view source**
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:content-type
Access-Control-Allow-Origin:http://localhost:8000
Cache-Control:no-cache
Content-Length:0
Date:Fri, 03 Feb 2017 18:09:04 GMT
Expires:-1
Pragma:no-cache
Server:"Management Corporation"
X-AspNet-Version:4.0.30319
**Request Headers view source**
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:mjvzrx3
Origin:http://localhost:8000
Referer:http://localhost:8000/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
So, it looks like I'm passing CORS, but when I get to trying to pass the data in as the content of the post, it doesn't make it.
Any ideas what I'm missing?
Thanks,
Nick
Web API expects an object in the message body, you cant pass in a primitive type unless you use application/x-www-form-urlencoded as the content-type and prefix the value with an equals = sign.
So you can fix it by one of these methods
Adjust the c# parameter and turning it into a type that has a string property and then send in a json object with a matching parameter name.
Change the request to url-encoding content type and add a = to the variable value.
Send it as a part of the URL instead of the message body, you can still use the POST method.
Change to form-urlencoded
function testapi()
{
var serviceRoot='http://server/testangular16/api/Values';
var deferred=$q.defer();
var req = {
method: 'POST',
url: serviceRoot,
data: '=PassInTheText', // added =
contentType: 'application/x-www-form-urlencoded' // specify content type
};
$http(req).then(goodResponse,badResponse);
return deferred.promise;
};
It seems if I do this, it works as expected.... Thoughts?
// POST api/values
public HttpResponseMessage Post(HttpRequestMessage request)
{
var data = request.Content.ReadAsStringAsync().Result;
Console.WriteLine("Data: {0}", data);
HttpResponseMessage rp = new HttpResponseMessage(HttpStatusCode.OK);
rp.Content = new StringContent("Data back from WebAPI" + data);
return rp;
}
My problem is that HTTP headers are not being sent from my AngularJS HTTP GET requests. However, for a HTTP POST, I do see the headers being set. These HTTP requests are over CORS.
Although there are a lot of SO posts on this problem, I have tried them and none of them worked. One of the solutions suggests that HTTP headers are not sent if the data field is empty, and I've tried the suggestion to add an empty data value (which doesn't really sense for a HTTP GET request, by the way), but still, the HTTP headers do not make it.
On a side note, I might defend that this post/question may merit itself as "not a duplicate" (from the other SO posts) as it deals with HTTP GET (as opposed to HTTP POST) and CORS (as opposed to not-CORS).
Here is my technology stack.
NodeJS v4.2.2
Express v4.13.3
AngularJS v1.4.0
To enable CORS, I followed the example here http://enable-cors.org/server_expressjs.html. My NodeJS server application looks like the following.
var express = require('express');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var jwt = require('jsonwebtoken');
var port = process.env.PORT || 8080;
var router = express.Router();
var app = express();
app.set('secret', 'mySecret');
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
app.use('/api', router);
router.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, x-access-token');
res.header('Access-Control-Allow-Methods', 'POST, PUT, GET, OPTIONS, DELETE');
next();
});
router.post('/authenticate', function(req, res) {
var username = req.body.username;
var pw = req.body.password;
if(username !== 'root') {
res.json({
success: false,
message: 'User not found'
});
} else if(pw !== 'root') {
res.json({
success: false,
message: 'Password wrong'
});
} else {
var user = {
username: username,
pw: pw
};
var token = jwt.sign(user, app.get('secret'), {
expiresIn: 60 * 60 * 24 * 365
});
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
});
router.use(function(req, res, next) {
/* according to comments, have to ignore OPTIONS request from protection */
if('OPTIONS' === req.method) { next(); return; } //original post modified here to show, after adding this line, the OPTIONS is accessible, then the GET does actually send the required HTTP header
if('/api/authenticate' === req.originalUrl) {
next();
return;
}
var token = req.body.token || req.params['token'] || req.headers['x-access-token'];
if(token) {
jwt.verify(token, app.get('secret'), function(err, decoded) {
if(err) {
return res.json({
success: false,
message: 'Failed to authenticate token'
});
} else {
req.decoded = decoded;
next();
}
})
} else {
return res.status(403).send({
success: false,
message: 'No token provided'
});
}
});
router.get('/users', function(req, res) {
res.json([
{ fname: 'john', lname: 'doe' },
{ fname: 'jane', lname: 'smith' }
]);
})
var server = app.listen(port, function() {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
My AngularJS service looks like the following.
myServices.factory('HomeService', ['$resource', '$http', '$location', '$cookies', 'conf', function($resource, $http, $location, $cookies, conf) {
var svc = {};
svc.getRestUrl = function() {
return 'http://localhost:8080';
};
svc.sendData = function(url, data, method) {
var restUrl = svc.getRestUrl() + url;
var options = {
method: method,
url: restUrl,
withCredentials: false
};
var token = $cookies.get('token');
if(_.isEmpty(token)) {
options.headers = {
'X-Requested-With': 'XMLHttpRequest'
};
} else {
options.headers = {
'X-Requested-With': 'XMLHttpRequest',
'x-access-token': token
};
}
if(data) {
options.data = data;
} else {
options.data = '';
}
return $http(options);
}
svc.getData = function(url) {
return svc.sendData(url, null, 'GET');
};
svc.postData = function(url, data) {
return svc.sendData(url, data, 'POST');
};
svc.authenticate = function(username, password) {
var data = JSON.stringify({
username: username,
password: password
});
return svc.postData('/api/authenticate', data);
};
svc.getUsers = function() {
return svc.getData('/api/users');
};
return svc;
}]);
Note
for the service's authenticate method, this is a HTTP POST
for the service's getUsers, this a HTTP GET
when there is no data to send (HTTP GET), the data is set to empty data: ''
Using Fiddler, for authenticate I see the following HTTP request.
POST http://localhost:8080/api/authenticate HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 37
Accept: application/json, text/plain, */*
Origin: http://localhost
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
{"username":"root","password":"root"}
For getUsers, I see the following HTTP request.
OPTIONS http://localhost:8080/api/users HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Access-Control-Request-Headers: accept, x-access-token, x-requested-with
Accept: */*
Referer: http://localhost/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Am I missing something here with regards to HTTP GET over CORS that the HTTP headers are not being sent?
According to your HTTP request, an OPTIONS request is fired to your CORS API icase of your getUsers method.
When it comes to CORS, there are 2 kinds of requests
Simple Requests
Preflighted Requests
Simple requests
A simple cross-site request is one that meets all the following conditions:
The only allowed methods are:
GET
HEAD
POST
Apart from the headers set automatically by the user agent, the only headers which are allowed to be manually set are:
Accept
Accept-Language
Content-Language
Content-Type
The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Preflighted requests
In case you make any request which violates the conditions of a simple request, then a "preflighted" OPTIONS request is sent in order to determine whether the actual request is safe to send.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)
For more details about Preflighted Requests, you can refer to this MDN link.
I believe this is what is happening in your case. Even though you're making a simple GET request, you're adding 2 custom headers X-Requested-With & x-access-token which makes it necessary to validate the safety of your API, so a preflighted OPTIONS request is sent by the browser. The browser will continue with your GET request only if it receives valid response.
In your NodeJS server code, you're handling only POST requests to /authenticate and GET requests to /users, so in case of an OPTIONS request, it's going to the default handler where you're checking for token and if it's not available, you respond with a 403. So I suggest you change your code to handle OPTIONS request as well.
I have an angularjs HTML client to a WebApi project. When I test the APIs via POSTMAN or other REST Client, it seems that everything is ok.
When I start using browsers with my angularjs client, browsers always start preflight requests with OPTIONS. There, my WebAPI always answers 400 Bad Request - I am still on a "/api/token" phase.
I have already attached every single point of my WebAPI project to the debugger. I have also changed several points according to several answers here in SO on how to enable CORS. Some of them I have already tried: changing web.config to add headers enabling cors on every request, adding cors to WebApi startup, enabling cors at "/token" overridden functions.
Here is what I got so for:
Angularjs TypeScript call to "/api/token":
logIn = (userName: string, userPassword: string): ng.IPromise<void> => {
var postData = {
"grant_type": "password",
"client_id": this.appConfiguration.ClientId,
"client_secret": this.appConfiguration.ClientSecret,
"username": userName,
"password": userPassword
};
return this.$http.post<models.LoggedUserModel>('http://local.web.api/api/token', $.param(postData), {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then((result) => {
this.localStorageService.set('Auth', result);
this.goHome(true);
}).catch((error) => {
console.warn(error);
});
}
Here is the only function that is called on my WebApi:
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// handle cors requests
if (!string.IsNullOrEmpty(context.OwinContext.Request.Headers.Get("Origin")))
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" });
}
try
{
// retrieve clientId and clientSecret from request body
string clientId;
string clientSecret;
if (context.TryGetFormCredentials(out clientId, out clientSecret))
{
// here it comes our application specific security code....
}
else
{
// this is part of enabling CORS..
if (context.Request.Method.ToUpper() == "OPTIONS")
{
// it returns OK to preflight requests having an empty body
context.Validated();
}
}
}
finally
{
// log stuff...
}
}
If I just left OWIN Cors stuff, adding headers and calling ´context.Validated()´ it all continues the same. Here is what I get:
Firefox Network Tab:
--------------------
Request URL: http://local.web.api/api/token
Request method: OPTIONS
Remote address: 127.0.0.1:80
Status code: 400 Bad Request
Version: HTTP/1.1
Request headers:
----------------
Host: local.web.api
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.7,pt-BR;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization
Origin: http://local.web.client
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Response headers:
-----------------
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Date: Tue, 22 Dec 2015 15:24:23 GMT
Expires: -1
Pragma: no-cache
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
I would really appreciate some ideas of where to got.
This is brand new to me, and I do operate some other WebApi projects + angularjs.
Ok, that's is terrible but I found the issue.
I am using a http interceptor on angularjs that would automatically check for a logged user and add an Authorization header with the Bearer token when needed. Problem is I was doing it wrongly.
I created a new property in the config object, bypassToken as boolean, that would be the flag to add or not the Authorization header. Removing this actually fixed the code. Not sure why, but analyzing the request now I can see that all headers are actually sending as expected: with the Content-Type which was not being filled on the first case correctly. Weird though no warning was thrown by angularjs.
// http auth interceptor
angularApplication.factory('httpAuthInterceptor', ['$rootScope', '$injector', '$location', ($rootScope, $injector, $location): ng.IHttpInterceptor => {
var $q: ng.IQService = $injector.get('$q');
var localStorageService: ng.local.storage.ILocalStorageService = $injector.get('localStorageService');
return {
request: (config: ng.IRequestConfig): ng.IRequestConfig => {
// check if headers are present
config.headers = config.headers || {};
// the error was here! I was trying to add properties to config that I think angular was not expecting
// removing this line solved the issue
// if (!config.bypassToken) {
// check if user is logged in
var loggedUserInfo = localStorageService.get<models.LoggedUserInfoModel>('Auth');
if (loggedUserInfo) {
config.headers['Authorization'] = 'Bearer ' + loggedUserInfo.access_token;
}
return config;
},
responseError: (rejection) => {
// check if user is logged in
var loggedUserInfo = localStorageService.get<models.LoggedUserInfoModel>('Auth');
if ((rejection.status === 401) && (loggedUserInfo)) {
// if so, then the user must login againd
localStorageService.remove('Auth');
$location.path('/home');
console.error(rejection);
}
return $q.reject(rejection);
}
};
}]);
I appreciate your help.
I am only posting this here in case someone faces a similar issue.
Don't mess with the config object!
I am working on api, which runs as Express JS app, and I am using Angular JS to send requests to that api.
The api requires authorization send in header and I am struggling to do that in angular.
My Express JS code:
app.all('*', function(req, res, next) {
// add details of what is allowed in HTTP request headers to the response headers
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Max-Age', '86400');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
// the next() function continues execution and will move onto the requested URL/URI
next();
});
app.use(function(req, res, next) {
var header=req.headers['authorization']||'', // get the header
token=header.split(/\s+/).pop()||'', // and the encoded auth token
auth=new Buffer(token, 'base64').toString(), // convert from base64
parts=auth.split(/:/), // split on colon
username=parts[0],
password=parts[1];
r(header);
r(token);
r(auth);
r(username);
r(password);
if(username=='usr' && password=='pwd'){
next();
}else{
res.set('WWW-Authenticate', 'Basic realm="Birds.cz login"');
res.status(401).send({error:'auth'});
}
}
When I use curl to send this: curl --user usr:pwd http://127.0.0.1:8000/v1/login, the console prints:
Basic dXNyOnB3ZA==
dXNyOnB3ZA==
usr:pwd
usr
pwd
which is correnct.
My angular service looks like this:
function testLogin() {
$http({
method :'GET',
url:'http://127.0.0.1:8000/v1/login',
}).success(function(data, status, headers, config) {
alert(data);
}).error(function(data, status, headers, config) {
alert('error');
}).catch(function(error){
alert('catch' + JSON.stringify(error));
});
}
and in config of the whole angular app I have:
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
//Enable cross domain calls
$httpProvider.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
// insert authorization header
var string = 'usr:pwd';
var encodedString = btoa(string);
$httpProvider.defaults.headers.common['Authorization'] = 'Basic ' + encodedString;
...
}
When I make request from Angular, the node js console prints five empty lines, therefore the Authorization header was not recognized at all.
Any ideas what is the problem?
EDIT When I use Authorization in http request header, the server returns error 0, but when I omit it, it returns error 401, as it should. It seems to me, that providing Authorization header breaks the code on server side before it sends the 401 error code.
EDIT 2 When I log the request header in node js app, it does not show token Authorization at all
{ host: '127.0.0.1:8000',
'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'cs,en-US;q=0.7,en;q=0.3',
'accept-encoding': 'gzip, deflate',
origin: 'http://localhost',
'access-control-request-method': 'GET',
'access-control-request-headers': 'authorization',
connection: 'keep-alive' }
EDIT 3 here is header of request, captured in firebug
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language cs,en-US;q=0.7,en;q=0.3
Access-Control-Request-He... authorization
Access-Control-Request-Me... GET
Connection keep-alive
Host 127.0.0.1:8000
Origin http://localhost
User-Agent Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Allow requests to come from different domains, add this code at server side to tackle CORS related error -
var resolveCrossDomain = function(req, res,next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.header("Access-Control-Allow-Credentials", true);
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
};
app.use(resolveCrossDomain);
I am making an authentication system based on tokens. When a user logs in a token sent back and this then submitted with each call to the server
Assigning a token
.factory('AuthenticationService', function($rootScope, $http, authService, $httpBackend) {
var service = {
login: function(user) {
$http.post('http://192.168.100.100/myApp/login', { user: user }, { ignoreAuthModule: true })
.success(function (data, status, headers, config) {
$http.defaults.headers.common.Authorization = data.authorizationToken;
console.log("token:" + data.authorizationToken);
authService.loginConfirmed(data, function(config) {
config.headers.Authorization = data.authorizationToken;
return config;
});
})
After this is executed calls are sent as OPTIONS rather than POST the problem being that I am sending to RESTful server and OPTIONS isn't ahhh ummm an option. i.e server expects POST, GET etc.
Chrome shows my headers as ..
General
**Remote Address:** 192.168.100.100:80
**Request URL:** http://192.168.100.100/myapp/login
**Request Method:** OPTIONS
**Status Code:** 404 Not Found
Response Headers
**Access-Control-Allow-Origin:** *
**Cache-Control:** no-cache, must-revalidate
**Connection:** Keep-Alive
**Content-Encoding:** gzip
**Content-Length:** 563
**Content-Type:** text/plain
**Date:** Tue, 04 Aug 2015 04:29:14 GMT
**Expires:** 0
**Keep-Alive:** timeout=5, max=100
**Server:** Apache/2.2.22 (Debian)
**Vary:** Accept-Encoding
**X-Powered-By:** PHP/5.4.41-0+deb7u1
Request Headers
OPTIONS /myapp/login HTTP/1.1
**Host:** 192.168.100.100
**Connection:** keep-alive
**Access-Control-Request-Method:** POST
**Origin:** null
**User-Agent:** Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
**Access-Control-Request-Headers:** authorization, content-type
**Accept:** */*
**Accept-Encoding:** gzip, deflate, sdch
**Accept-Language:** en-US,en;q=0.8
Will it always be OPTIONS and do I have to alter my RESTful server to accomodate this, should I not be able to see the token in the headers?
This is an preflight request to check if CORS are enaabled or not
During the preflight request, you should see the following two headers: Access-Control-Request-Method and Access-Control-Request-Headers. These request headers are asking the server for permissions to make the actual request. Your preflight response needs to acknowledge these headers in order for the actual request to work.
Shortly. You need to enable these headers at you server for actual request to work
Can you please check if CORS is enabled? if yes please try to handle OPTIONS request like this
if (req.method === 'OPTIONS') {
console.log('!OPTIONS');
var headers = {};
// IE8 does not allow domains to be specified, just the *
// headers["Access-Control-Allow-Origin"] = req.headers.origin;
headers["Access-Control-Allow-Origin"] = "*";
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
headers["Access-Control-Allow-Credentials"] = false;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
res.writeHead(200, headers);
res.end();
}