AngularJs - JSON post - ajax

I tried to post username and password to api, but looks like it doesnt work as simple as jquery post. I keep geting this 400 error.
Code:
$http({
method: 'POST',
url: apiLink + '/general/dologin.json',
data: {"username":"someuser","password": "somepass"}
}).success(function(response) {
console.log(response)
}).error(function(response){
console.log(response)
});
But if I add this line:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
and change data to:
data: "username=someuser&password=somepass"
it works. But the thing is, that I have to use json.
And detailed informations from Google Chrome:
Request URL:http://coldbox.abak.si:8080/general/dologin.json
Request Method:POST
Status Code:400 Bad Request
Request Headersview source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en,sl;q=0.8,en-GB;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:57
Content-Type:application/x-www-form-urlencoded
Host:coldbox.abak.si:8080
Origin:http://localhost:8888
Referer:http://localhost:8888/
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36
Form Dataview sourceview URL encoded
{"username":"someuser","password":"somepass"}:
Response Headersview source
Access-Control-Allow-Origin:*
Connection:close
Content-Length:49
Content-Type:application/json;charset=utf-8
Date:Wed, 02 Apr 2014 07:50:00 GMT
Server:Apache-Coyote/1.1
Set-Cookie:cfid=b5bbcbe2-e2df-4eef-923f-d7d13e5aea42;Path=/;Expires=Thu, 31-Mar-2044 15:41:30 GMT;HTTPOnly
Set-Cookie:cftoken=0;Path=/;Expires=Thu, 31-Mar-2044 15:41:30 GMT;HTTPOnly

I'm betting it's a CORS issue if your angular app isn't on the exact same domain as the server to which you're posting your JSON.
See this answer for details: AngularJS performs an OPTIONS HTTP request for a cross-origin resource

Try
data: {username:"someuser",password: "somepass"}
without the quotes around the username and password and see if that makes a difference.

You would have to transform the data with a JSON.stringify when you assign that to the data

Related

No response for XHR request in python with requests.get()

I want to scrape german poll data from a server. Here, I search for an examplary street, straße "Judengasse".
I have been trying to reproduce this. Unfortunately, the link from the reference is not intact anymore, so I couldn't directly compare it to my problem. Since I am fairly inexperienced, I do not know what is exactly needed to reproduce the request that is submitted via the web interface.
I don't now which attributes of the header are needed for my request to work and what of it might be redundant. In Chrome's inspect mode I see that in my case there are more header attributes than in the referenced example.
My code so far (which does not work) from trying to reproduce the SE post:
import requests
url = 'https://online-service2.nuernberg.de/Finder/action/getItems'
data = {
"finder":"Wahlraumfinder",
"strasse":"Judengasse",
"hausnummer":"0"
}
headers = {
'Host': 'online-service2.nuernberg.de',
'Referer': 'https://online-service2.nuernberg.de/Finder/?Wahlraumfinder',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7',
'Connection': 'keep-alive',
'Content-Length': '312',
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryeJZfrnZATOw6B5By',
'DNT': '1',
'Host': 'online-service2.nuernberg.de',
'Referer': 'https://online-service2.nuernberg.de/Finder/?Wahlraumfinder',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'
}
response = requests.get(url, data=data, headers=headers)
I don't get a respone. I added all request headers to headers.
Not sure, if more headers are needed.
Further, I am not sure if the url is correct.
I am looking to generate output of the following form, for this specific request "Judengasse":
Nr 0652
Wahllokal Willstätt.-Gym., Innerer Laufer Platz 11
This corresponds to putting in "Judengasse" into the search bar and hitting go on
the search "Suche" and extracting parts of the first output box "Wahl-/Stimmbezirk"
When I look at the XHR in Chrome's dev mode:
General
Request URL: https://online-service2.nuernberg.de/Finder/action/getItems
Request Method: POST
Status Code: 200 OK
Remote Address: 193.22.166.102:443
Referrer Policy: no-referrer-when-downgrade
Response Header
Connection: Keep-Alive
Content-Length: 1149
Content-Type: application/json;charset=UTF-8
Date: Wed, 04 Dec 2019 00:21:30 GMT
Keep-Alive: timeout=5, max=100
Server: Apache
Request Header
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Content-Length: 312
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx2jHYJHo3ejnKw0l
DNT: 1
Host: online-service2.nuernberg.de
Origin: https://online-service2.nuernberg.de
Referer: https://online-service2.nuernberg.de/Finder/?Wahlraumfinder
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
X-Requested-With: XMLHttpRequest
From Data
------WebKitFormBoundaryx2jHYJHo3ejnKw0l
Content-Disposition: form-data; name="action"
"action/getItems"
------WebKitFormBoundaryx2jHYJHo3ejnKw0l
Content-Disposition: form-data; name="data"
{"finder":"Wahlraumfinder","strasse":"Judengasse","hausnummer":"0"}
------WebKitFormBoundaryx2jHYJHo3ejnKw0l--
Thank you for reading.
After some research I finally managed to get a 200 response from this server.
Firstly, requests.get in this case should be replace by requests.post, since you want to replicate an HTTP POST request, according to the info you got from Chrome's dev mode, "General" section.
Secondly, from the headers we can see that the data is sent as being of type "multipart/form-data" request. As far as I could understand, this is a type of request that is used to send files instead of regular data (more about this type of request here).
So, I converted the string sent through the POST request to binary (this is achieved by prepending b) and passed it to the files parameter of the request. For some reason, this parameter requires a tuple (a, b) inside a set {c}, hence the {(None, data)}.
I also passed the street name as a parameter to data, so it's easier to manipulate it.
I got this working code (I'm using my browser's request):
import requests
url = 'https://online-service2.nuernberg.de/Finder/action/getItems'
street = b'Judengasse'
data = b'-----------------------------15242581323522\r\n' \
b'Content-Disposition: form-data; name=\"action\"\r\n\r\n' \
b'\"action/getItems\"\r\n-----------------------------15242581323522\r\n' \
b'Content-Disposition: form-data; name="data"\r\n\r\n' \
b'{\"finder\":\"Wahlraumfinder\",\"strasse\":\"%s\",\"hausnummer\":\"0\"}\r\n' \
b'-----------------------------15242581323522--' % street
headers = {"Host": "online-service2.nuernberg.de",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br",
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "multipart/form-data; boundary=---------------------------15242581323522",
"Content-Length": "321",
"Origin": "https://online-service2.nuernberg.de",
"DNT": "1",
"Connection": "keep-alive",
"Referer": "https://online-service2.nuernberg.de/Finder/?Wahlraumfinder",
}
multipart_data = {(None, data,)}
response = requests.post(url, files=multipart_data, headers=headers)
print(response.text)
I got this raw response:
{"id":"8c4f7a57-1bd6-423a-8ab8-e1e40e1e3852","items":[{"zeilenbeschriftung":"Wahl-/Stimmbezirk","linkAdr":null,"mapUrl":"http://online-service.nuernberg.de/Themenstadtplan/sta_gebietsgli
ederungen.aspx?p_urlvislayer=Stimmbezirke&XKoord=4433503.05&YKoord=5480253.301&Zaehler=1&Textzusatz=Judengasse+0&z_XKoord=4433670.0&z_YKoord=5480347.0&z_Zaehler=1&z_Textzusatz=Wahllokal%
20Willst%E4tt.-Gym.%2C+Innerer+Laufer+Platz+11","items":["0652","Judengasse, Neue Gasse","Willstätt.-Gym., Innerer Laufer Platz 11","Zi. 101 ,1. OG",null]},{"zeilenbeschriftung":"Stimmkr
eis Landtagswahl","linkAdr":null,"mapUrl":"http://online-service.nuernberg.de/Themenstadtplan/sta_gebietsgliederungen.aspx?p_urlvislayer=Stimmkreis_LTW&XKoord=4433503.05&YKoord=5480253.3
01&Zaehler=1&Textzusatz=Judengasse+0&p_scale=100000","items":["501","Nürnberg-Nord"]},{"zeilenbeschriftung":"Wahlkreis Bundestagswahl","linkAdr":null,"mapUrl":"http://online-service.nuer
nberg.de/Themenstadtplan/sta_gebietsgliederungen.aspx?p_urlvislayer=Wahlkreis_BTW&XKoord=4433503.05&YKoord=5480253.301&Zaehler=1&Textzusatz=Judengasse+0&p_scale=150000","items":["244","N
ürnberg-Nord"]}],"status":200}
which you can easily parse to get the result you expect:
print(response.json()["items"][0]["items"])
yilding...
['0652', 'Judengasse, Neue Gasse', 'Willstätt.-Gym., Innerer Laufer Platz 11', 'Zi. 101 ,1. OG', None]
Hope it helps.
Regards

unsupported media type application/x-www-form-urlencoded

I'm getting this error all of a sudden:
21:28:14.345 [debug] ** (Plug.Parsers.UnsupportedMediaTypeError) unsupported media type application/x-www-fo
rm-urlencoded
(plug) lib/plug/parsers.ex:231: Plug.Parsers.ensure_accepted_mimes/4
(api) lib/api/router.ex:1: Api.Router.plug_builder_call/2
(api) lib/plug/debugger.ex:123: Api.Router.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/Ben/Development/Projects/vepo/api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
When making this network request:
Request URL:http://192.168.20.6:4000/products/?p_id=1&s_id=1
Request Method:PUT
Status Code:415 Unsupported Media Type
Remote Address:192.168.20.6:4000
Referrer Policy:no-referrer-when-downgrade
Response Headers
view source
cache-control:max-age=0, private, must-revalidate
content-length:45284
content-type:text/html; charset=utf-8
date:Sun, 28 Jan 2018 08:40:36 GMT
server:Cowboy
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-GB,en-US;q=0.9,en;q=0.8
Connection:keep-alive
Content-:application/json
Content-Length:75
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Host:192.168.20.6:4000
Origin:http://evil.com/
Referer:http://localhost:8081/debugger-ui/debuggerWorker.js
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
X-Requested-With:XMLHttpRequest
Query String Parameters
view source
view URL encoded
p_id:1
s_id:1
Form Data
view source
view URL encoded
s_id:1
p_id:1
image:null
price:2.53
description:kcucufufi icif Gigiuyub
Code to send the request:
import { ajax } from 'rxjs/observable/dom/ajax'
return ajax({
body: action.payload,
method: 'PUT',
headers: { 'Content-': 'application/json' },
url: `http://192.168.20.6:4000/products/?p_id=${
action.payload.p_id
}&s_id=${action.payload.s_id}`
}).map(response => updateEditProductInDbFulfilled(response))
.catch(error => Observable.of(updateEditProductInDbRejected(error)))
I didn't actively change anything in my backend to not accept x-www-form-urlencoded, so why would this happen when it used to work?
Is x-www-form-urlencoded bad? What is the best approach to successfully send my network request? Change my code sending the request or changing the backend somehow to accept the request?
Backend is Elixir.
This is how I added Plug.Parsers (In my router):
if Mix.env == :dev do
use Plug.Debugger
end
plug :match
plug Plug.Parsers, parsers: [:json],
pass: ["application/json"],
json_decoder: Poison
plug :dispatch

Angular's $http.post doesn't work, nor does its' $http... but jQuerys ajax does. Why?

For some reason this:
return jquery.ajax('my url', {
crossDomain : true
, data : JSON.stringify({"brand": self.current})
, type : 'POST'
}).success(function(data){
scope.results = data;
});
and/or this:
curl -X POST -H "Content-Type: application/json" -d '{"brand":"target"}' myUrl
work fine, but this:
var req = {
method: "POST"
, url : "my url"
, data : JSON.stringify({"brand": self.current})
};
return $http(req).
success(function(data){
scope.results = data;
});
fails miserably with
"OPTIONS my url (anonymous function) # angular.js:9866sendReq # angular.js:9667$get.serverRequest # angular.js:9383processQueue # angular.js:13248(anonymous function) # angular.js:13264$get.Scope.$eval # angular.js:14466$get.Scope.$digest # angular.js:14282$get.Scope.$apply # angular.js:14571(anonymous function) # angular.js:21571jQuery.event.dispatch # jquery.js:4430jQuery.event.add.elemData.handle # jquery.js:4116
(index):1 XMLHttpRequest cannot load my url. No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:5000' is therefore not allowed access. The response had HTTP status code 404."
They're the same url. Wtf.
I have a sneaking suspicion that the "crossDomain : true" option in jquery is why the jquery one works, but if that's the case, then the question is:
how do I do that with angular?
-- When using jquery's default ajax method, the scope isn't updating with the results, but i know the data is being assigned because i'm logging it out, and if i submit the request again, the scope does update with the second value.
Second question- why isn't my view updating with the results?
update:
The reason this is failing has nothing to do with the response I'm getting back from the server, the problem is that Angular is transforming this POST request into an OPTIONS request:
(taken from google chromes' xhr tool:)
Remote Address: the remote address
Request URL:the request endpoint
Request Method:OPTIONS <-------------
Status Code:404 Not Found
Further inspection reveals:
OPTIONS /my url HTTP/1.1 <--------------
Host: my urls host
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:5000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36
Access-Control-Request-Headers: accept, charset, content-type
Accept: */*
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
which is not what it should be doing because I'm specifically saying in the req object i'm passing to $http that this is a POST request.
...
So how do I make angular... NOT do that?
also- why is it doing that?
When you do a cross-origin request from your browser, all browsers hit the URL (provided in AJAX call) to confirm if the cross-origin request is available or not which is known as preflight request. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
So, your server's endpoint must allow the preflight request in order to make this call work by setting some response headers like (an example in Groovy):
response.setHeader "Access-Control-Allow-Headers", "Content-Type"
response.setHeader "Access-Control-Allow-Methods", "POST,DELETE,PUT"
response.setHeader "Access-Control-Allow-Origin", "*"

WebAPI 2 and post parameters in body passed as null

I have a webapi2 controller method as below:
[Route("shipment/{shipmentId:long}/quotes/register")]
public HttpResponseMessage ProvideQuote(long shipmentId, [FromBody]RegisterQuote quote)
{
HttpResponseMessage response;
response = Request.CreateResponse(HttpStatusCode.Accepted, String.Format("quote of price {0} for shipment {1} has been registred", quote.QuotePrice, shipmentId));
return response;
}
now the issue is that when I test the method using my REST client, the quote is always null.
here is how I am testing
parameter
now the response I get is:
as you can see that the query string parameter is being passed correctly, but the body parameter is not passed. any idea what am I doing wrong.
Edit 1:
Request Header:
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
Authorization: Bearer Hhz54k1BLyPMJxucSeq4pLwhS3Y4Ez5WCoEMzhe-uH7gHMFMRjHE2Im9juinMLhqaHVZmkVrWetEiCsYbaduzLas7rYf-D3p40lH_q3IDEn2rdt122qpiHvnUr7Cz2b6GXiPYLGDMQFOMN0lbkYmoZe95sxXDRvDfpdJw4G2Fk3Ri1A25F3qAZCnBhjA-BLoL-2eAjxX-RPCGAXjaNLjT4zsxRJH8NP5qC7azPrWCDKRuK282hnTbKViQjMBDflwlxdPhTNkiCBtxWn03xRcxH9GD1z5Ca0Qinn5gUS7qWwCt9zoZtHcbwFY1kvxyx7x5yCuyEfrGHgKG1s7zjTPjNwU0eV7cC6xQA2GsOAnqADxMDyRryCRKLY7WcyQftRhZ70WbtSW2PI0F7qmDr8n0wvktmKglusLEDf4ib925n-ajVTyMl7v9O-9OsdgCj_GSNE6_bszd3Ak1yUurs-VoQ
Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,kn;q=0.6
BTW I am not sure what happened to all my images though!
Regards
Kiran
The issue here is that you are sending Json content in the body but have the content-type header as application/x-www-form-urlencoded...change the content-type header to application/json or text/json if want to send data in json...

Please help me understand Ajax request versus Backbone fetch()

My app can currently hit our API with a standard JQuery Ajax GET request and get good data back. CORS has been properly implemented on the remote server as far as I can see. Here are the response headers:
company_client_envelope_id: 88764736-6654-22e4-br344-a1w2239a892d
access-control-allow-headers: X-Requested-With, Cookie, Set-Cookie, Accept, Access-Control
Allow-Credentials, Origin, Content-Type, Request-Id , X-Api-Version, X-Request-Id,Authorization, COMPANY_AUTH_WEB
access-control-expose-headers: Location
response-time: 55
request-id: 88764736-6654-22e4-br344-a1w2239a892d
company_api_version: 0.01.09
server: localhost
transfer-encoding: chunked
connection: close
access-control-allow-credentials: true
date: Sun, 09 Feb 2014 14:44:05 GMT
access-control-allow-origin: *
access-control-allow-methods: GET, POST
content-type: application/json
However, using Backbone and calling the same GET request by using fetch() causes the following CORS error:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
I cannot figure out what the difference is. Both requests are running from localhost.
In the case of the AJAX query, the following is being sent as requested by the API guys:
headers: {
"accept":"application/json"
}
And in the case of the model and collection declaration I am sending the headers like so:
MyApp.someCollection = Backbone.Collection.extend(
{
model:MyApp.someModel,
headers: {
'Accept':'application/json',
'withCredentials': 'true'
},
url: MYCOMPANY_GLOBALS.API + '/endpoint'
});
and my fetch is simply:
someCollection.fetch();
===============================
Added in response to: #ddewaele
These are the headers from the network tab:
Request URL:http://api-blah.com:3000/
Request Headers CAUTION: Provisional headers are shown.
Accept:application/json
Cache-Control:no-cache
Origin:http://localhost
Pragma:no-cache
Referer:http://localhost/blah/blah/main.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107Safari/537.36
There is no pre-flight or remote headers from the API server:
many thanks,
Wittner
I've recommended to you rewrite Backbone.sync method, because in your app you have some security field for example and other reason.
var oldBackboneSync = Backbone.sync;
// Override Backbone.Sync
Backbone.sync = function (method, model, options) {
if (method) {
if (options.data) {
// properly formats data for back-end to parse
options.data = JSON.stringify(options.data);
}
// transform all delete requests to application/json
options.contentType = 'application/json';
}
return oldBackboneSync.apply(this, [method, model, options]);
}
You can add different headers as you want.

Resources