HTTP POST request for JSON in Perl - json

I'm trying to configure the wireless settings (like setting ssid as "vinoth" channel as "1") in Linksys EA4500 AP. I could see the below POST message using wireshark.
3E##!dPzY+2K
SPOST /JNAP/ HTTP/1.1
Host: 192.168.1.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:22.0) Gecko/20100101 Firefox/22.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=UTF-8
X-JNAP-Action: http:cisco.com/jnap/core/Transaction
X-JNAP-Authorization: Basic YWRtaW46YWRtaW4=
X-Requested-With: XMLHttpRequest
Referer: http:/cisco.com/ <<<<==== routerip
Content-Length: 474
Cookie: initial-tab=; ui-proxy-path=local; admin-auth=Basic%20YWRtaW46YWRtaW4%3D; current-applet=7B1F462B-1A78-4AF6-8FBB-0C221703BEA4
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
[{"action":"http:/cisco.com/jnap/wirelessap/SetRadioSettings","request":{"radios":[{"radioID":"RADIO_2.4GHz","settings":{"isEnabled":true,"mode":"802.11bgn","ssid":"vinoth","broadcastSSID":true,"channelWidth":"Auto","channel":1,"security":"None"}}]}},{"action":"http://cisco.com/jnap/guestnetwork/SetGuestNetworkSettings","request":{"isGuestNetworkEnabled":false,"guestSSID":"vinoth-guest","guestPassword":"BeMyGuest","maxSimultaneousGuests":5,"broadcastGuestSSID":false}}]
I tried automating the above action using Perl but it didn't workout. As I am new to this JSON page I don't know how exactly the POST message to be sent.
content I kept for $json is
'{"action":"http:/cisco.com/jnap/wirelessap/SetRadioSettings",' .
'"request":{"radios":{"radioID":"RADIO_2.4GHz","settings":'.'{"isEnabled":true,"mode":"802.11bgn","ssid":"vinoth212","broadcastSSID":true,"channelWidth":"Auto","channel":1,"security":"None"}}}},{"action":"http://cisco.com/jnap/guestnetwork/SetGuestNetworkSettings",' .
'"request":{"isGuestNetworkEnabled":false,"guestSSID":"vinoth-guest","guestPassword":"BeMyGuest","maxSimultaneousGuests":5,"broadcastGuestSSID":false}}';
and the code:
use strict;
use warnings;
use LWP;
my $ua = LWP::UserAgent->new;
my $ip = $self->{ip};
my $url = "http://$ip/";
my $json = "";
my $req = HTTP::Request->new(POST=>$url);
$req->header('content-type' => 'application/json');
$req->authorization_basic("admin", "admin");
$req->content($json);
Below code for checking the request status
my $res = $ua->request($req);
if ($res->is_success) {
my $message = $res->decoded_content;
print "received the message";
} else {
print "HTTP get code: ", $res->code, "\n";
print "HTTP get: msg: ", $res->message, "\n";
}
Please help me in fixing this. Awaiting for your valuable reply.
P.S: In the Wireshark Post message the links are not proper as I am unable to post the query with more than 2 links.
Thanks,
Vinoth

Using the code $req->authorization_basic("admin", "admin"); it means Authorization: Basic YWRtaW46YWRtaW4= HTTP header when make any request.
But From your wireshirk's header it is X-JNAP-Authorization: Basic YWRtaW46YWRtaW4=, which is different thing(a custom header). So remove that authorization_basic from your block and use these ones:
$req->header('Content-Type' => 'application/json; charset=UTF-8');
$req->header('X-JNAP-Action' => 'http:cisco.com/jnap/core/Transaction');
$req->header('X-JNAP-Authorization' => 'Basic YWRtaW46YWRtaW4=');
## YWRtaW46YWRtaW4= is base64 of admin:admin
$req->header('X-Requested-With' => 'XMLHttpRequest');

Related

Ajax request returns bad request error code

I am getting a bad request response to my request. I have checked with an online JSON validator my dictionary data to be correct, and everything seems fine.
My code is the following:
// Parse datetime to timestamp and include data in a dict
let data_dict = {
"stop_date": Date.parse(sup_limit.value),
"start_date": Date.parse(inf_limit.value)
}
// Send the Ajax request
let request = $.ajax({
url: url,
type: 'POST',
data: data_dict,
contentType: 'application/json;charset=UTF-8',
});
Backend receive endpoint:
#dashboard_bp.route('/download_last_test_influx<mode>', methods=['GET', 'POST'])
#login_required
def download_last_test_influx(mode: str):
# Check if request comes from a custom or test event
if mode == 'custom':
start_date = int(request.json.get('start_date'))
stop_date = int(request.json.get('stop_date'))
# Check if time range is valid, if not return server internal error
if stop_date - start_date <= 0:
return jsonify({'message': 'Time range must be grater than 0'}), 500
# Create response header
response = make_response(send_file(spock_comm_mgr
.test_backup_influx_manager
.get_last_test_influx_record(start_date=start_date, stop_date=stop_date)))
response.headers['Content-Type'] = 'application/gzip'
response.headers['Content-Encoding'] = 'gzip'
return response
Request header:
POST /download_last_test_influxcustom HTTP/1.1
Host: 0.0.0.0:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json;charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 48
Origin: http://0.0.0.0:5000
Connection: keep-alive
Referer: http://0.0.0.0:5000/influx_management
Cookie: *********************
Request payload:
stop_date=1623758400000&start_date=1623708000000
Response message:
Bad Request
The browser (or proxy) sent a request that this server could not understand.
You are telling your server, you are sending JSON data, but the request body is not a JSON string but a url-encoded string (because that's the default behaviour of $.ajax() when you pass an object as data).
Use JSON.stringify, to pass a correct JSON body
let request = $.ajax({
url: url,
type: 'POST',
data: JSON.stringify(data_dict),
contentType: 'application/json;charset=UTF-8',
});

AEM JCR - Get response as JSON

We are adding some metadata under a specific location in JCR:
POST /some/jcr/location/_jcr_content/json HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46YWRtaW4=
Cache-Control: no-cache
Host: localhost:4502
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: multipart/form-data; boundary=--------------------------554953211468377919703514
Cookie: cq-authoring-mode=TOUCH
Content-Length: 383
----------------------------554953211468377919703514
Content-Disposition: form-data; name="./value"
{ "test": "test" }
----------------------------554953211468377919703514
Content-Disposition: form-data; name=":cq_csrf_token"
ey***our csrf token***-c5Oa0
----------------------------554953211468377919703514--
But when we fetch this same resource, the response type is test/html`:
GET /some/jcr/location/jcr:content/json/value HTTP/1.1
Accept: application/json
Cache-Control: no-cache
Host: localhost:4502
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: cq-authoring-mode=TOUCH
HTTP/1.1 200 OK
Date: Fri, 26 Feb 2021 13:49:38 GMT
X-Content-Type-Options: nosniff
Content-Type: text/plain;charset=utf-8
Content-Length: 18
{ "test": "test" }
What configuration do we need to add in JCR, or what do we need to edit in our request to make sure that JCR returns content type application/json.
UPDATE: As Sharath Madappa replied, you can request the data in JSON format by suffixing the location with the .json extension. However, that results in the following format:
{
"value": "{ \"test\": \"test\" }"
}
While I expect it to be:
{
"test": "test"
}
use GET /some/jcr/location/jcr:content/json/value.json while making the request. Sling is able to render/return the resource in multiple formats based on the extension in the request. By default, if no extension is provided it goes with HTML. The path tells which resource, the extension, and selectors tell how and what renders the resource.
You can also specify the depth you want to go for besides having JSON format response.
E.g
Depth of 1(just the node) in JSON format:
curl -u <user>:<pass> -v <URL>/some/jcr/location/jcr:content/json/value.1.json
All child nodes under a certain path in JSON format:
curl -u <user>:<pass> -v <URL>/some/jcr/location.-1.json
Posting JSON content and then retrieving it as Content-Type: application/json can be done by file upload instead of adding properties.
Here is a javascript example:
const data = { test: "test" };
const jsonData = new Blob([JSON.stringify(data)], { type: 'application/json' });
const formData = new FormData();
formData.append(`myFile.json`, jsonData, `myFile.json`);
return fetch(path, {
method: 'POST',
body: formData
});
This example does not take in account Authn/Authz.
To fetch you data as application/json, you just issue a GET call to the location of the JSON file:
http://localhost:4502/path/to/the/folder/jcr:content/files/myFile.json

Receive Json sent from Angular to Laravel

I'm trying to send a json to the backend, here is the piece of code that I use to send data:
register(user): Observable<any>{
let json = JSON.stringify(user);
let params = 'json='+json;
let headers = new HttpHeaders().set('Content-Type', 'aplication/x-www-form-urlencoded');
console.log(json);
console.log(params);
console.log(headers);
return this._http.post('http://api-rest-laravel.com.devel/api/register', params, {headers: headers});
}
This is the code in the backend:
public function register(Request $request) {
Log::info("Datos: " . $request);
$json = $request->input('json', null);
$params = json_decode($json);
$params_array = json_decode($json, true); //Array
Log::info("Json: " . $json);
if (!empty($params) && !empty($params_array)) {
//register
}else{
//send error msg
}
If i try the backend using Postman, this is what i get from Request param:
[2020-10-04 15:37:36] local.INFO: Datos: POST /api/register HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 229
Content-Type: application/x-www-form-urlencoded
Cookie: laravel_session=eyJpdiI6InoxMG53RXZTTGZaV0h3dFF6VmVDUXc9PSIsInZhbHVlIjoiZ2V6ZEFYNjZKOSt0K0RPMmgra0FCMVUwMkhIb0JGSjJ6cW53VkhKSnUwV1ViWENVZTNDaXl3UzlBckZVYXRCSSIsIm1hYyI6ImM2YzA0MjEzYzRjMTEzNmQxYmY4NTJmNDRhNzk1ZGJmZGQwOGU2NmQ2NDM5OWM2MDcwNjFjNmJiMTIzNDIyM2MifQ%3D%3D
Host: api-rest-laravel.com.devel
Postman-Token: 47cfbc5a-136c-424d-9e1b-f61c18c2fc5c
User-Agent: PostmanRuntime/7.26.5
Cookie: laravel_session=pi7VHwGsyzTB36rK7KdbtAUU4GGagUNSklMQliqL
json=%7B%22id%22%3A1%2C%22name%22%3A%22qwer%22%2C%22surname%22%3A%22qwe%22%2C%22role%22%3A%22ROLE_USER%22%2C%22email%22%3A%22qqwer22%40asd.com%22%2C%22password%22%3A%22qqq%22%2C%22description%22%3A%22%22%2C%22image%22%3A%22%22%7D
[2020-10-04 15:37:36] local.INFO: Json: {"id":1,"name":"qwer","surname":"qwe","role":"ROLE_USER","email":"qqwer22#asd.com","password":"qqq","description":"","image":""}
[2020-10-04 15:37:36] local.INFO: goes toIF
and this is request param if I try it in browser ($json is empty, second last line):
[2020-10-04 15:40:30] local.INFO: Datos: POST /api/register HTTP/1.1
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: es-ES,es;q=0.9,en;q=0.8
Connection: keep-alive
Content-Length: 127
Content-Type: aplication/x-www-form-urlencoded
Dnt: 1
Host: api-rest-laravel.com.devel
Origin: http://localhost:4200
Referer: http://localhost:4200/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
json={"id":1,"name":"qwe","surname":"qwe","role":"ROLE_USER","email":"qqwe#asd.com","password":"q","description":"","image":""}
[2020-10-04 15:40:30] local.INFO: Json:
[2020-10-04 15:40:30] local.INFO: goes to ELSE
I also tried to send from frontend a json simillar to the one sent from postman to see if that was the problem. Didn't work.
//return this._http.post('http://api-rest-laravel.com.devel/api/register', 'json=%7B%22id%22%3A1%2C%22name%22%3A%22qwer%22%2C%22surname%22%3A%22qwe%22%2C%22role%22%3A%22ROLE_USER%22%2C%22email%22%3A%22qqwer222%40asd.com%22%2C%22password%22%3A%22qqq%22%2C%22description%22%3A%22%22%2C%22image%22%3A%22%22%7D', {headers: headers});
Why is this happening? I'm newbie with angular and laravel and I didnt find a solution so far. Corse is OK
in your header :
let headers = new HttpHeaders().set('Content-Type','application/json')

POST request is success, but Chrome get XMLHttpRequestError

I'm trying to upload binary file (to Amazon S3) from my localhost Vue page, using Amazon API Gateway with CORS enabled.
Actual POST Request have issued after Preflight Request issued.
And file upload have succeed.
But the POST Request have caught error bellow.
I don't know Why got the error?
Chrome(Version 79.0.3945.79)
got message
Access to XMLHttpRequest at 'https://XXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/upload' from origin 'http://192.168.0.20:8080' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
AXIOS ERROR: Error: Network Error
at createError (createError.js?2d83:16)
at XMLHttpRequest.handleError (xhr.js?b50d:81)
Source code
async upload() {
console.log("file:", this.file);
const axiosConfig = {
headers: {
"Content-Type": "image/png"
}
};
axios
.post("https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/upload", this.file, axiosConfig)
.then(res => {
console.log("RESPONSE RECEIVED: ", res);
})
.catch(err => {
console.log("AXIOS ERROR: ", err);
});
Header(Preflight Request)
Request
:authority: XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com
:method: OPTIONS
:path: /dev/upload
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,ja;q=0.8
access-control-request-headers: content-type
access-control-request-method: POST
origin: http://192.168.0.20:8080
referer: http://192.168.0.20:8080/
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36
Response
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
access-control-allow-methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
access-control-allow-origin: *
content-length: 0
content-type: application/json
date: Fri, 13 Dec 2019 12:39:40 GMT
status: 200
via: 1.1 88c2e4442XXX3f0dXXX7df6fcXXX37ff.cloudfront.net (CloudFront)
x-amz-apigw-id: EpH19E9sNjMFhOg=
x-amz-cf-id: PEXXXH0x8_mlAspmv-xhi3X3XXXn_LSBswhXXXyqnCGZmVPkXXXYhw==
x-amz-cf-pop: NRT51-C1
x-amzn-requestid: 47XXc915-3b44-4XX7-959a-3XXX62150b3d
x-cache: Miss from cloudfront
Header(Actual POST)
Request
:authority: XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com
:method: POST
:path: /dev/upload
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,ja;q=0.8
content-length: 6849
content-type: image/png
origin: http://192.168.0.20:8080
referer: http://192.168.0.20:8080/
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36
Response
content-length: 47
content-type: application/json
date: Fri, 13 Dec 2019 12:39:40 GMT
status: 200
via: 1.1 88c2e44426XX3f0db837df6fc92437ff.cloudfront.net (CloudFront)
x-amz-apigw-id: EpH1_EeptjMFXqw=
x-amz-cf-id: XXqDis00oJqvh8wY-a0sugE6tuhwPHiJLs7ucXX5OdPC0uoCql7-nQ==
x-amz-cf-pop: NRT51-C1
x-amzn-requestid: 9XXX54a0-0a71-4cda-9d91-ae90a3322c9f
x-amzn-trace-id: Root=1-5XXX868c-fXXXa33dd82751efXXX547d;Sampled=0
x-cache: Miss from cloudfront
I solved it myself.
I don't know Why got the error?
Because Response header includes NO 'access-control-allow-origin'.
Browser could't read response body by CORB (Cross-Origin Read Blocking).
Added the header to response in Lambda function, it works.
s3.putObject({
Body: requestBody,
Bucket: "xxxxxx.com",
ContentType: "image/png",
Key: "uploadTest/logo.png"
})
.promise()
.then(result => {
const message = JSON.stringify(result);
callback(null, {
body: message,
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*"
}
});
});

How to read json data of a bad request (status code 400) using Alamofire

I was calling a Rest API locally from terminal. This was like below:
http -v -f --timeout=60 GET 'http://localhost:8080/api/v1/public/users/signin?email=myemail#email.com&password=mypassword'
It is returning following output:
GET /api/v1/public/users/signin?email=myemail#email.com&password=mypassword HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: localhost:8080
User-Agent: HTTPie/0.8.0
HTTP/1.1 400 Bad Request
Content-Type: application/json
Date: Mon, 28 Mar 2016 16:59:08 GMT
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Sun, 27- Mar-2016 16:59:13 GMT
Transfer-Encoding: chunked
{
"debugMessage": "Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - najmul#qianalysis.com, rememberMe=true] did not match the expected credentials.Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - najmul#qianalysis.com, rememberMe=true] did not match the expected credentials.: The subject was expected to be true, but was false",
"errorCode": "INCORRECT_CREDENTIALS",
"logId": "50a695c1a81e0542",
"stackTrace": "org.niopack.r.....
}
Now I want to read this JSON data using Alamofire. I tried with responseJSON serialiser with following way:
Alamofire.request(method, urlString, parameters: parameters, encoding: .URL, headers: cookieHeader)
.validate()
.responseJSON {
alamofireResponse in
let jsonData = alamofireResponse.result.value
}
But this I am getting jsonData as nil. What you will do if you were are here?
Thanks.
For me removing the validate() allowed me to see the reason the request was failing. For some reason when validate fails, the data of the response is not parsed.