8

I'm trying to talk with an API using TypeScript and JQuery (from Definitely Typed).

let ajaxsettings: JQueryAjaxSettings = {
    url: this.url,
    contentType: "application/json",
    type: "POST",
    data: JSON.stringify(this.apiRequest),
    processData: false,
    success: ( data, textStatus, jQxhr ) => {
        console.log("Response:" + JSON.stringify(data));
    },
    error: ( jqXhr, textStatus, errorThrown ) => {
        console.log("Error Response; " + JSON.stringify(jqXhr));
    },
    headers: {
        "X-UserName": "blahblah",
        "X-Password": "blahblah"
    },
    beforeSend: (request) => {
        request.setRequestHeader("X-APIKey", "blahblahblah");
    }
};
$.ajax(ajaxsettings);

Making the request and looking at what Fiddler captures is rather odd.

Fiddler JQuery request

Wrong HTTP verb, and headers are included in Access-Control-Request-Headers not as a standard header.

JQuery 3.2.0, and the latest index.d.ts from Definitely Typed.

I could create a HTTP request in Fiddler:

Fiddler request

The request I'm trying to create:

Fiddler output

Update

I've tried juggling the dataType to get around preflight checks:

contentType : "text/plain",
method: "POST",
type: "post",
dataType: "json",

Update 2

The API is hosted within IIS Express from Visual Studio 2017 (using .NET Core), and the website is hosted using lite-server. This code works fine, when taking out the custom headers.

Community
  • 1
  • 1
wonea
  • 3,987
  • 17
  • 71
  • 134
  • This is just a wild guess, but according to the jQury API documentation you should use `method` in favor of `type` prior 1.9. – Sebastian Sebald Apr 11 '17 at 09:19
  • Thanks, I've changed type: to data: but it still comes through as OPTIONS rather than POST – wonea Apr 11 '17 at 09:25
  • Could you create a minimal example, so we can test your code? :) – Sebastian Sebald Apr 11 '17 at 09:26
  • 2
    http://stackoverflow.com/questions/1256593/why-am-i-getting-an-options-request-instead-of-a-get-request – robC Apr 11 '17 at 09:28
  • I've updated my question with a few attempt to get around this. – wonea Apr 11 '17 at 10:24
  • You "tried juggling the dataType to get around preflight checks", but you still send custom headers `X-UserName` and `X-Password`. [MDN says](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS): <> (and the list follows). Can you remove those headers and make that info part of the JSON blob you send? (if you can change the service side...) – Hugues M. May 15 '17 at 09:37
  • so, this is basically [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) doing it´s thing. what is your backend technology? Also, from what URL are you serving your script? – earloc May 15 '17 at 10:55
  • @HuguesMoreau It's frustrating because works fine with .NET clients, and the headers come across fine there. – wonea May 15 '17 at 15:53
  • 1
    I see, but a browser has restrictions that a .NET (or any other kind of) HTTP client does not have. You could keep that service as is for non-browser clients, and have another "proxy/relay" service that would expose it in a browser-friendly way, by relaying requests from browsers (with everything CORS entails) to the real backend service. – Hugues M. May 15 '17 at 15:55
  • This is not TypeScript specific in a meaningful way. Can you add the [JavaScript] tag? – Aluan Haddad May 18 '17 at 16:25
  • I guess you should use `Content-Type` as `application/x-www-form-urlencoded` in request header – Amol Bhor May 22 '17 at 15:41

1 Answers1

5

This is just normal CORS doing its work. Make sure you are serving the html-site containing your script from the same URL/Port where your API is located. e.g.:

your Html/Script should be located under

http://localhost:1234/web/index.html

then an AJAX-call to

http://localhost:1234/api/Controller

should be no problem, as the script issuing the request originates from the same URL/Port and there is no need to do a check.

This way, you should circumvent the need for a pre-flight check of the browser which determines if the request is granted access according to CORS.

Alternatively, enable CORS in your API, but make sure you don´t expose the API to be callable from every possible (Web-)client out there, to prevent misuse.

Another possible route to gain more control over your URL´s might be to switch to full IIS even on your DEV-machine, but there might be other/better ways to achieve this (am myself not so deep into hosting .NET Core ATM to provide a better sample, but others might)

Community
  • 1
  • 1
earloc
  • 1,895
  • 9
  • 19