second angular $http request doesn't reach its destination - javascript

I'm setting up a oauth-like flow, where making an actual request is postponed until some preliminary negotiation has completed.
The preliminary negotiation works, but when I try to make the request for the desired resource, I get the following behavior:
The django server logs a POST request for each step in the negotation.
The angular client logs an OPTIONS and a POST request for each step in the negotation.
So far so good.
Next, I get an OPTIONS request for the resource. This request gets stuck on pending in the browser, while $http's request function executes the error callback with a status of 0.
I get an error message from angular saying: failed to load resource.
This is the request object I'm passing to $http:
cache: false
data: null
headers: {
Authorization: OAuth realm="all"oauth_consumer_key="21846675797"oauth_signature_method="PLAINTEXT"oauth_token="89676366323"oauth_timestamp="1376236699"oauth_nonce="dQBGqqTQf"oauth_signature="GET&localhost%3A16080%2Fkauth%2Ftest%2F&oauth_consumer_key%3D%2221846675797%22%26oauth_nonce%3D%22dQBGqqTQf%22%26oauth_signature_method%3D%22PLAINTEXT%22%26oauth_timestamp%3D%221376236699%22%26oauth_token%3D%2289676366323%22"
}
method: "GET"
params: null
url: "localhost:16080/kauth/test/"
I deleted all standard headers, out of fear they might interfere with my signature:
$http.defaults.headers.common = {};
$http.defaults.headers.get = {};
$http.defaults.headers.post = {};
$http.defaults.useXDomain = true;
The django server logs nothing for this request.
Any pointers would be appreciated.

I found the answer...
Including the protocol (http://) at the beginning of the url does the trick.

Related

Angular 5 HttpClient.put executes two requests

I'm building PWA with Angular 5. And having problem with duplicated execution of PUT requests. I'm also running POST and GET requests but this bug appears only with PUT.
This is the method
put(url: string, data: string): Observable<any> {
console.log('put');
const options = {
headers: new HttpHeaders({
'Content-Type': 'text/xml'
})
};
return this.http
.put(url, data, options).map(resp => {
console.log('put_output');
return resp;
});
}
It makes two requests when this method runs only once.
Network tab screenshot:
Console output screenshot:
I've tried to run simple XMLHttpRequest and it was perfect: one request, one response.
The first request is a Preflighted Request, this behavior is OK, and some developers call it "Handshake with server".
From DOCS:
"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.
You can also check the issue here.

AngularJs - Server throwing exception''XMLHttpRequest cannot load the "URL" Response for preflight is invalid (redirect)'

What is the reason the server is returning object as 'undefined' and 'XMLHttpRequest cannot load the "URL" Response for preflight is invalid (redirect).
Flow of app - its just a normal post service sending document details to the server in return should return an object holding various parameters, but its returning 'undefined'
The service for posting the document
fileUpload: {
method: 'POST',
url: config.apiPath + 'employee/service/pushRecords', //this is the URL that should return an object with different set of parameters (currently its returning Error error [undefined])
isArray: false,
params: {},
headers: {
'content-type': undefined
}
},
above service i have used after creating formdata w.r.t document
function registerFormdata(files, fieldName) {
files = files || [];
fieldName = fieldName || 'FileSent';
var returnData = new FormData();
_.each(files, function (file, ind) {
returnData.append(fieldName,file);
});
return returnData;
}
now this is the controller where these services are used
function sendFilesToServer() {
var formData = employeePushService.registerFormdata(directive.dropZoneFile.fileToUpload);
return docUploadService.fileUpload(formData)
.then(function(document) {
// Extra actions but here the server should be returning an object with set of parameters but in browser console its Error [undefined]
}).catch(logger.error);
}
Assuming that the URL target in yout post is correct, it seems that you have a CORS problem, let me explain some things.
I don't know if the server side API it's developed by yourself, if it is, you need to add the CORS access, your server must return this header:
Access-Control-Allow-Origin: http://foo.example
You can replace http://foo.example by *, it means that all request origin will have access.
First, you need to know that when in the client you make an AJAX CORS request, your browser first do a request to the server to check if the server allow the request, this request is a OPTION method, you can see this if, for example in chrome, you enable the dev tools, there, in the network tab you can see that request.
So, in that OPTIONS request, the server must set in the response headers, the Access-Control-Allow-Origin header.
So, you must check this steps, your problem is that the server side is not allowing your request.
By the way, not all the content-type are supported in CORS request, here you have more information that sure will be helpfull.
Another link to be helpfull for the problem when a 302 happens due to a redirect. In that case, the POST response must also include the Access-Control-Allow-Origin header.

POST going as OPTIONS in firebase node js http request [duplicate]

I am working on an internal web application at work. In IE10 the requests work fine, but in Chrome all the AJAX requests (which there are many) are sent using OPTIONS instead of whatever defined method I give it. Technically my requests are "cross domain." The site is served on localhost:6120 and the service I'm making AJAX requests to is on 57124. This closed jquery bug defines the issue, but not a real fix.
What can I do to use the proper http method in ajax requests?
Edit:
This is in the document load of every page:
jQuery.support.cors = true;
And every AJAX is built similarly:
var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
url: url,
dataType: "json",
data: json,
async: true,
cache: false,
timeout: 30000,
headers: { "x-li-format": "json", "X-UserName": userName },
success: function (data) {
// my success stuff
},
error: function (request, status, error) {
// my error stuff
},
type: "POST"
});
Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. If you're doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain. This is why the jQuery bug was closed as won't-fix. This is by design.
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)
Based on the fact that the request isn't sent on the default port 80/443 this Ajax call is automatically considered a cross-origin resource (CORS) request, which in other words means that the request automatically issues an OPTIONS request which checks for CORS headers on the server's/servlet's side.
This happens even if you set
crossOrigin: false;
or even if you ommit it.
The reason is simply that localhost != localhost:57124. Try sending it only to localhost without the port - it will fail, because the requested target won't be reachable, however notice that if the domain names are equal the request is sent without the OPTIONS request before POST.
I agree with Kevin B, the bug report says it all. It sounds like you are trying to make cross-domain ajax calls. If you're not familiar with the same origin policy you can start here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript.
If this is not intended to be a cross-domain ajax call, try making your target url relative and see if the problem goes away. If you're really desperate look into the JSONP, but beware, mayhem lurks. There really isn't much more we can do to help you.
If it is possible pass the params through regular GET/POST with a different name and let your server side code handles it.
I had a similar issue with my own proxy to bypass CORS and I got the same error of POST->OPTION in Chrome. It was the Authorization header in my case ("x-li-format" and "X-UserName" here in your case.) I ended up passing it in a dummy format (e.g. AuthorizatinJack in GET) and I changed the code for my proxy to turn that into a header when making the call to the destination. Here it is in PHP:
if (isset($_GET['AuthorizationJack'])) {
$request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}
In my case I'm calling an API hosted by AWS (API Gateway). The error happened when I tried to call the API from a domain other than the API own domain. Since I'm the API owner I enabled CORS for the test environment, as described in the Amazon Documentation.
In production this error will not happen, since the request and the api will be in the same domain.
I hope it helps!
As answered by #Dark Falcon, I simply dealt with it.
In my case, I am using node.js server, and creating a session if it does not exist. Since the OPTIONS method does not have the session details in it, it ended up creating a new session for every POST method request.
So in my app routine to create-session-if-not-exist, I just added a check to see if method is OPTIONS, and if so, just skip session creating part:
app.use(function(req, res, next) {
if (req.method !== "OPTIONS") {
if (req.session && req.session.id) {
// Session exists
next();
}else{
// Create session
next();
}
} else {
// If request method is OPTIONS, just skip this part and move to the next method.
next();
}
}
"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
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Consider using axios
axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {
if(res.data.error) {
} else {
doAnything( res.data )
}
}).catch(function (error) {
doAnythingError(error)
});
I had this issue using fetch and axios worked perfectly.
I've encountered a very similar issue. I spent almost half a day to understand why everything works correctly in Firefox and fails in Chrome. In my case it was because of duplicated (or maybe mistyped) fields in my request header.
Use fetch instead of XHR,then the request will not be prelighted even it's cross-domained.
$.ajax({
url: '###',
contentType: 'text/plain; charset=utf-8',
async: false,
xhrFields: {
withCredentials: true,
crossDomain: true,
Authorization: "Bearer ...."
},
method: 'POST',
data: JSON.stringify( request ),
success: function (data) {
console.log(data);
}
});
the contentType: 'text/plain; charset=utf-8', or just contentType: 'text/plain', works for me!
regards!!

$http.get not sending data in the body of the request

Using angular v1.3.1 i got a singular the following problem trying to implement a facade for making http request to a REST + JSON interface in the backend of the web app.
I got something like this in the code:
findSomething(value: number): ng.IPromise<api.DrugIndication[]> {
const getParams = { 'param' : 'value' };
const config:ng.IRequestShortcutConfig = {
headers: {
"Content-Type" : "application/json"
},
data: getParams
}
return this.$http.get(url,config);
}
And when the times comes to invoke it, i got an 400 Bad Request (btw: Great name for a band!) because the backend (made with Play for Scala) rejects the request inmediately. So making an inspection in the request i see that no data is being send in the body of the request/message.
So how i can send some data in the body of and HTTP Get request using angular "$http.get"?
Additional info: This doesn't happen if i the make request using the curl command from an ubuntu shell. So probably is an problem between Chrome and angular.js
If you inspect the network tab in chrome development tools you will see that this is a pre-flight OPTIONS request (Cross-Origin Resource Sharing (CORS)).
You have two ways to solve this.
Client side (this requires that your server does not require the application/json value)
GET, POST, HEAD methods only
Only browser set headers plus these
Content-Type only with:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Server side
Set something like this as a middleware on your server framework:
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
w.Header().Set("Access-Control-Max-Age", "86400") // firefox: max 24h, chrome 10min
return
}
For your specific framework this should work
Using config.data will send the data in the request body, use
config.params = getParams
This is from the documentation :
params – {Object.} – Map of strings or objects which will be serialized with the paramSerializer and appended as GET parameters

Sending and receiving data using javascript http

I am sending data in json format from javascript using XMLHttpRequest and receiving data at node.js file as following
client.js
$.ajax({
type: "POST",
dataType: 'json',
data: JSON.stringify(Idata),
url: AjaxURL,
success: function (result) {
return true;
}
});
server.js
var http = require('http');
console.log("server initialized");
var server = http.createServer(function (req, response) {
req.on('data', function (data) {
var d = JSON.parse(data);
console.log("data : " + d.OperationType);
});
req.on('end', function () {
response.end();
});
}).listen(3000);
Now i successfully got the value of operationtype but the at client browser this error is showing:
XMLHttpRequest cannot load http://localhost:3000/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
The primary problem is that you are making a "GET" request. A data payload/HTTP request body cannot be uploaded with an XMLHttpRequest "GET" request. See the specification of XMLHttpRequest: "If stored method is GET act as if the data argument is null."
In order to send data, you should make a "POST" request, in this case:
xmlhttp.open("POST", AjaxURL, true);
In response to updated question:
For security reasons, your AJAX request will not be allowed to access your server hosted at localhost:3000 unless the AJAX request is initiated from a page served by localhost:3000 OR you tell your server to allow "cross-origin" requests. The latter can be accomplished by adding a line like this to your server:
response.setHeader("Access-Control-Allow-Origin", "*");
This sets a header that tells the browser to allow AJAX requests to localhost:3000 even if the request is initiated from a page that was not served by localhost:3000.
Please do the following:
In client.js, output the value Idata(using console.log) right before sending it.
Use the 'Network' tab in Chrome(or equivalent in your favorite browser) to check what is actually being sent.
In server.js, output the value data(using console.log) right after recieving it.
That will probably give you a clue as to where it went wrong, which will help you determine your next course of action. If you still don't know how to proceed, update the question and I will update my answer.
What I can say right now based on my (very lacking) knowledge of node.js, is that if the variable data is being treated as an object, store += data; is not a good idea, as that would mean you are trying to add an object to an (empty) string.
(Probably resulting in the object returning "[object Object]", or some such)

Categories