Converting cURL to angular 2 HTTP POST - javascript

I want to convert this cURL to angular 2 post request
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -H "Authorization: Basic cGJob2xlOmlJelVNR3o4" -H "Origin: http://localhost:4200/form" -H "Postman-Token: fbf7ede1-4648-a330-14ee-85e6c29ee80d" -d 'content=Queue: tsi-testdesk' "https://testdesk.ebi.ac.uk/REST/1.0/ticket/new?user=USER&pass=PASS"
here is the code i wrote but its not working.
addForm(form: Form): Observable<Form> {
console.log(" SUBMITTING FORM");
let headers = new Headers();
this.loginService.writeAuthToHeaders(headers);
// JSON.stringify(headers);
// headers.append('Accept', 'application/x-www-form-urlencoded');
headers.append('Content-Type', 'application/x-www-form-urlencoded');
// let text = JSON.stringify(form)
let content = ('content:Queue: tsi-testdesk');
console.log(content);
return this.http.post('https://testdesk.ebi.ac.uk/REST/1.0/ticket/new?user='+this.credentialsService.getUsername()+'&pass='+this.credentialsService.getPassword(), content, { headers: headers })
// .map(response => <Form>response.json())
.catch(this.handleError);
}
It is giving me pre-flight response fail error but it works fine with cURL as well as POSTMAN and also I Dont have access to server side I am contacting it through API

CORS is a policy that is enforced by the web browser. Ultimately, it is up to the browser, whether or not it will allow a cross-origin request. In the case of cURL or Postman, there is no browser, there is no current HOST, so there is not even the concept of a cross-origin request. Technically Postman is a Chrome extension, but it is not at all the same thing as loading a web page and making cross-origin requests.
Public-facing API's (probably like the one you are trying to access) already have CORS enabled. The likely culprit is your own server. You must enable CORS requests on your web server so it will allow you to make requests to outside APIs.

Related

Can I use Node.js packages, such as request, to scrape the AngularJS response on this WA government website?

I'm trying to go to the WA Secretary of State Corporations website (https://ccfs.sos.wa.gov/#/AdvancedSearch) to scrape data on newly incorporated companies. All of this data is publicly available.
I filter the data by setting Business Type to WA PROFIT CORPORATION (towards bottom), Business Status to ACTIVE, and any random 30 day window for Start Date and End Date for the Date of Incorporation date range. I then click Search.
The first thing I notice is there is no query string, so the DB isn't accessible via a query string. So, I opened up Chome Dev Tools and went to the Network tab. If you refresh the page you'll notice that there's an AngularJS XHR file that loads in under the Name GetAdvanceBusinessSearchList.
If I Preview this file, all of the data I need is neatly structured in JSON format. If I try opening the file in another tab to see the query string I receive an error "The requested resource does not support http method 'GET'".
I've tried accessing the data using the Node Request module. I've tried both GET requests and POST requests. I assumed POST was the correct route once I received the GET error mentioned above. When fired off my POST request I also included some Form Data that I found in the Dev Tools, but the response I received was that it didn't support multipart/form-data.
I've also tried using the Puppeteer module, and I can get to the search results, but then because the content is loaded in using an Angular file, none of the HTML elements have IDs and it becomes a sloppy mess trying to mine all of the data.
const request = require('request');
request.get('https://cfda.sos.wa.gov/api/BusinessSearch/GetAdvanceBusinessSearchList', (err, res, body) => { console.log(body) });
My goal is to get access to the JSON structured data that can be found by previewing the GetAdvanceBusinessSearchList file in the Network tab of the Chrome Dev Tools once you've submitted a search.
Any help would be hugely appreciated.
This worked for me:
curl 'https://cfda.sos.wa.gov/api/BusinessSearch/GetAdvanceBusinessSearchList' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:68.0) Gecko/20100101 Firefox/68.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.8,es-AR;q=0.5,es;q=0.3' --compressed -H 'Referer: https://ccfs.sos.wa.gov/' -H 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' -H 'Origin: https://ccfs.sos.wa.gov' -H 'Connection: keep-alive' --data 'Type=Agent&BusinessStatusID=0&SearchEntityName=&SearchType=&BusinessTypeID=0&AgentName=&PrincipalName=&StartDateOfIncorporation=&EndDateOfIncorporation=&ExpirationDate=&IsSearch=true&IsShowAdvanceSearch=true&&&AgentAddress%5BIsAddressSame%5D=false&AgentAddress%5BIsValidAddress%5D=false&AgentAddress%5BisUserNonCommercialRegisteredAgent%5D=false&AgentAddress%5BIsInvalidState%5D=false&AgentAddress%5BbaseEntity%5D%5BFilerID%5D=0&AgentAddress%5BbaseEntity%5D%5BUserID%5D=0&AgentAddress%5BbaseEntity%5D%5BCreatedBy%5D=0&&AgentAddress%5BbaseEntity%5D%5BModifiedBy%5D=0&&AgentAddress%5BFullAddress%5D=%2C%20WA%2C%20USA&AgentAddress%5BID%5D=0&&&&AgentAddress%5BState%5D=WA&&AgentAddress%5BCountry%5D=USA&&&&&&&&PrincipalAddress%5BIsAddressSame%5D=false&PrincipalAddress%5BIsValidAddress%5D=false&PrincipalAddress%5BisUserNonCommercialRegisteredAgent%5D=false&PrincipalAddress%5BIsInvalidState%5D=false&PrincipalAddress%5BbaseEntity%5D%5BFilerID%5D=0&PrincipalAddress%5BbaseEntity%5D%5BUserID%5D=0&PrincipalAddress%5BbaseEntity%5D%5BCreatedBy%5D=0&&PrincipalAddress%5BbaseEntity%5D%5BModifiedBy%5D=0&&PrincipalAddress%5BFullAddress%5D=%2C%20WA%2C%20USA&PrincipalAddress%5BID%5D=0&&&&PrincipalAddress%5BState%5D=&&PrincipalAddress%5BCountry%5D=USA&&&&&&PageID=1&PageCount=25'

The "Authorization" header is not sent in OPTIONS call by the browser

I have a very simple HTTP call:
fetch('http://127.0.0.1:5500/v1/homes/', {
method: "GET",
mode: "cors",
credentials: "same-origin",
headers: {
Authorization: "TEST"
}})
.then(function(response) {
console.log(response);
});
But when I look into the "Networks" tab of Google Chrome DevTools, the OPTIONS request does not have the "Authorization" header in it. This causes the server to replies with 401 Unauthorized.
The browser's curl equivalent of the request:
curl 'http://127.0.0.1:5500/v1/homes/' \
-X OPTIONS -H 'Access-Control-Request-Method: GET' \
-H 'Origin: http://localhost:8100'
-H 'Referer: http://localhost:8100/'
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
-H 'Access-Control-Request-Headers: authorization'
--compressed
Am I doing something wrong in the client side or is it quite common that browsers do not send the Authorization header in OPTIONS request, and therefore, I need to change the server in a way to response to OPTIONS call without requiring Authorization header?
is it quite common that browsers do not send the Authorization header in OPTIONS request
More than common. It is required by the CORS spec which says "for a cross-origin request with preflight … make a preflight request … Exclude user credentials".
I need to change the server in a way to response to OPTIONS call without requiring Authorization header?
Yes
An Options call is requested by the client, in your case Chrome browser implicitly before the actual GET call.
From MDN
The HTTP OPTIONS method is used to describe the communication options
for the target resource. The client can specify a URL for the OPTIONS
method, or an asterisk (*) to refer to the entire server.
On the server side, you'll have to intercept this Options request and respond back with a HTTP Status code of 200 and a Allow header indicating the operations that are permitted on this resource. eg: Allow: HEAD,GET,PUT,DELETE,OPTIONS
The browser on receiving these details will then proceed with the Get call.

JIRA authentication using Javascript

I'm trying to perform basic authentication for JIRA, by using JIRA's REST API.
JIRA's website does provide a CURL command to get this done:
curl -D- -u fred:fred -X GET -H "Content-Type: application/json"
http://example.com/rest/api/2/issue/createmeta
When I run this in Chrome, I'm getting the following error:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access
When I run this code in IE, I'm getting the following response, but I know using * for access control defeats the purpose CORS:
{"self":"https://mypersonaljiraurl.org/jira/rest/api/latest/user?
username=12345","name":"12345","loginInfo":
{"failedLoginCount":2,"loginCount":50}}
I wrote the following code in Javascript to make a HTTP request.
var request = new XMLHttpRequest();
request.open("GET", "https://mypersonaljiraurl/rest/auth/1/session", false);
request.setRequestHeader("Authorization", authenticateUser(userName, passWord));
request.setRequestHeader("Content-Type", 'application/json');
request.setRequestHeader('Access-Control-Allow-Origin', '*');
request.send();
alert(request.status);
response.innerHTML = request.responseText;
How do I resolve this so it can work in Chrome? Would it be better to do this with Jquery/Ajax?

Unable to create session using SessionToken in okta POST /sessions API call

I was able to get the sessionToken using username and password. But, after that I want to create the session using POST call as follows in AngularJS. The angular (entire web app) is hosted on AWS S3.
var session_data = { 'sessionToken' : My_session_Token};
$http({
method: 'POST',
url: 'https://myorg.okta.com/api/v1/sessions',
data: session_data,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then(function(response) {
console.log(response);
});
The error I am getting is
XMLHttpRequest cannot load https://myorg.okta.com/api/v1/sessions. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://s3.amazonaws.com' is therefore not allowed access.
I have already added the CORS Allow origin header in Okta as well as S3 bucket.
When I try doing the following through terminal
curl -v -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"sessionToken": "my_session_Token"
}' "https://myorg.okta.com/api/v1/sessions"
First time I get
{"errorCode":"E0000005","errorSummary":"Invalid session","errorLink":"E0000005","errorId":"oaefADOnPONTDidUZYyrVc5rQ","errorCauses":[]}MAC-S014568:~
second time, because of sessionToken is one time use only I get following error
{"errorCode":"E0000004","errorSummary":"Authentication failed","errorLink":"E0000004","errorId":"oaeI-KKSO-iRGSR1gmyUjBS8g","errorCauses":[]}MAC-S01
I don't think the problem is because of the CORS header (Allow origin) as I have already added the origin.
Also, I cannot use SSWS {api_TOKEN} as my application is in angular and its risky to expose the api token.
Any help will be highly appreciated
Okta doesn't support POSTing to /api/v1/sessions to set a cookie in the browser. For a simple use case, you can use the redirect flow:
window.location = 'https://myorg.okta.com/login/sessionCookieRedirect?token={sessionToken}&redirectUrl={redirectUrl}';
All the allowed methods of setting a cookie using a sessionToken are listed here: http://developer.okta.com/use_cases/authentication/session_cookie

Why sending a POST by AJAX is interpreted by the HTTP Server as OPTIONS and sending by CURL is effectively a PUT?

I'm testing a HTTP Server that I have developed myself with C++ and Boost libraries. More specifically, I'm testing an endpoint where a JSON is received by PUT.
To test the RESTFul webservice I use Curl with the following command:
curl -H "Content-Type: application/json" -H "Content-Length: 34" -H "Connection: close" -X PUT --data "#response_json" http://localhost:8080/answer
where response_json is a file with the json to be sent. This works fine, the server receives the request as a PUT and do what is supposed to do.
However, when I test the webservice from AJAX with this:
function sendPut2() {
var http = new XMLHttpRequest();
var url = 'http://localhost:8080/answer';
var data = JSON.stringify({"question": "a", "answer": "b"});
http.open("PUT", url, true);
http.setRequestHeader("Content-type", "application/json");
http.setRequestHeader("Content-Length", data.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(data);
}
the server receives it as OPTIONS and does not work. Moreover, in Firebug console I can see: "NetworkError: 404 Not Found - http://localhost:8080/answer".
I have tried with Firefox and Chrome. What is wrong in my javascript code?
This is the Firebug with the request from Javascript:
The browser has a same origin policy for security reasons. When you request a Ajax PUT in the browser from a different origin than the current web page was loaded from, then the request is subject to that same origin policy. The destination site can choose to support CORS (cross origin resource sharing) which is a specific scheme that the browser implements that lets it ask the target site if a specific cross origin request is OK or not.
Using the OPTIONS request before the PUT request is one such part of the CORS scheme. If the browser detects certain conditions on the original cross origin request, then it will first issue an OPTIONS request and, if it gets the right response from that, then it will issue the target request (a PUT in your case). Things that can trigger the browser to use the OPTIONS request are things like custom headers, certain types of authorization required, certain content types, certain types of requests, etc...
CURL, on the other hand, enforces no such same origin security (that is someting a browser invented for its own web page security model) so it just sends the PUT request right through without requiring the correct answer from the OPTIONS request first.
FYI, if the Javascript in the browser that is making the Ajax request is requesting from the same origin as the loaded web page that contains the Javascript, then it should not trigger the OPTIONS request because it would be a same origin request rather than a cross origin request. If you have a local server, make sure that the web page is being loaded from the local server (same hostname and port number) too, not from the file system and not one using an IP address and the other using localhost or something like that. As far as the browser is concerned, the hostname has to physically be the same, not just the same IP address.
Here's info from MDN on what requests are "preflighted" with the OPTIONS request:
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)
FYI, here's a pretty good explanation of the various aspects of CORS. Because your request is a PUT, it will be in the "not-so-simple request" part of that article.

Categories