Getting bad request error with alamofire JSON request - json

I have been converting this curl syntax
curl -L -X POST 'https://driver-vehicle-licensing.api.gov.uk/vehicleenquiry/v1/vehicles' \-H 'x-api-key: REPLACE WITH YOUR API KEY' \-H 'Content-Type: application/json' \-d '{"registrationNumber": "TE57VRN"}'
into Swift with Alamofire and have got this syntax
guard let url = URL(string: "https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles") else { return }
let headers : HTTPHeaders = [
"x-api-key": "mykey",
"Content-Type": "application/json"
]
let params: Parameters = [
"registrationNumber" : "myreg"
]
AF.request(url, method: .post, parameters: params, encoding: URLEncoding(destination: .httpBody), headers: headers).responseJSON(completionHandler: { response in
print(response)
})
However, I have got the output
success({
errors = (
{
code = ENQ103;
detail = "Invalid format for field - vehicle registration number";
status = 400;
title = "Bad Request";
}
);
Please could someone explain what I have done wrong. Thanks

The API expects the parameters to be sent as JSON, but you are sending as URL encoded.
Try using JSONParameterEncoder.default as the encoder instead of URL encoding.
Check Usage from the docs: POST request with JSON Parameters
let parameters: Parameters = [
"registrationNumber" : "myreg"
]
AF.request(url, method: .post, parameters: parameters, encoder: JSONParameterEncoder.default)

You have a working curl command, small (or big) tip: AlamoFire can print the request as a curl command!
In "one step":
AF.request(url, method: .post,
parameters: params,
encoding: URLEncoding(destination: .httpBody),
headers: headers)
.cURLDescription(calling: { curlCommand in
print("curlCommand1: \(curlCommand)")
}).responseJSON(completionHandler: { response in
print(response)
})
In "two steps", if you prefer to separate your calls and not chain them all:
let request = AF.request(url, method: .post,
parameters: params,
encoding: URLEncoding(destination: .httpBody),
headers: headers)
request.cURLDescription { curlCommand in
print("curlCommand2: \(curlCommand)")
}
request.responseJSON(completionHandler: { response in
print(response)
})
And you should have output:
curl -v \
-X POST \
-H "Accept-Encoding: br;q=1.0, gzip;q=0.9, deflate;q=0.8" \
-H "User-Agent: Alamofired/1.0 (...; build:1; iOS 14.5.0) Alamofire/5.4.0" \
-H "Accept-Language: en;q=1.0, fr-US;q=0.9" \
-H "Content-Type: application/json" \
-H "x-api-key: mykey" \
-d "registrationNumber=myreg" \
"https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles"
Now, if we compare with yours:
curl \
-L \
-X POST \
'https://driver-vehicle-licensing.api.gov.uk/vehicleenquiry/v1/vehicles' \
-H 'x-api-key: REPLACE WITH YOUR API KEY' \
-H 'Content-Type: application/json' \
-d '{"registrationNumber": "TE57VRN"}'
I added some \ to make it sill valid...
We shouldn't care about the order, the "Accept-Language", "User-Agent", "Accept-Encoding" headers that are added with Alamofire shouldn't be an issue.
Try your command with no -L parameter maybe to check if it's "important" (if it's --location).
And then, the difference is with the data paramater (-d). Once is JSON, the other is URL encoded.
Then, let's see your code, and URLEncoding(destination: .httpBody)
might be the culprit. Using JSONEncoding.default instead will work.
Now, if you didn't have had the curl command, just by seeing your code, I spotted it. If you think about it:
You are saying there that you will provide the parameter in body following the JSON protocol.
let headers : HTTPHeaders = ["Content-Type": "application/json"]
And later, you used URL Encoding protocol.
URLEncoding(destination: .httpBody)
Doesn't make sense, right? You're contradicting yourself.

Related

How to Parse Data into a POST request for MRPeasy

TLDR
For my API project I require to send a POST request to MRP to update some of the fields.
What I am currently struggling with is the ability to parse in the parameters as data, every time I send the request I get a code 400.
Full Explanation
MRPeasy has a documentation page which I am using heavily for this project as that is the only source of info.
In that article they give 2 examples, 1 for GET and 1 for POST, I have no issues whatsoever with the get request, it works perfectly fine. However, the POST does not, they are as follows:
curl -X "GET" "https://app.mrpeasy.com/rest/v1/items" \
-H 'Content-Type: application/json' \
-H 'api_key: xxxxxxxxxxxxx' \
-H 'access_key: xxxxxxxxxxxxx'
curl -X "PUT" "https://app.mrpeasy.com/rest/v1/items/5" \
-H 'Content-Type: application/json' \
-H 'api_key: xxxxxxxxxxxxx' \
-H 'access_key: xxxxxxxxxxxxx' \
-d '{"selling_price": "2.54"}'
Below is my representation of the above code in python:
```python
url = "https://app.mrpeasy.com/rest/v1/manufacturing-orders/69"
headers = {
"Content-Type": "application/json",
"api_key": my_api_key,
"access_key": my_access_key
}
print(requests.get(url, headers=headers).json()["custom_3338"])
url = "https://app.mrpeasy.com/rest/v1/manufacturing-orders/69"
headers = {
"Content-Type": "application/json",
"api_key": my_api_key,
"access_key": my_access_key
}
data = json.dumps({"custom_3338": "1654642800.0000000000"})
print(requests.post(url, headers=headers, data=data).status_code)
```
Regarding the data variable, I have tried all of the below:
'{"custom_3338": "1654642800.0000000000"}'
{"custom_3338": "1654642800.0000000000"}
{"due_date": "1654642800.0000000000"}
{"quantity": 3}
'{"quantity": 3}'
I hope that is sufficient information. If you need anything else from me, please let me know, I'll be more than happy to provide.
Many Thanks,
Greg
P.S. This is my first post so I apologise if I didn't follow some rules or best practices.
You can create a json File contains the data you want to send as data and send the request with the JSON file itself.
JSON
{"custom_3338": "1654642800.0000000000"}
curl
curl -X POST \
-H 'Content-Type: application/json' \
-H 'api_key: xxxxxxxxxxxxx' \
-H 'access_key: xxxxxxxxxxxxx'
--data "#./processGroup.json" \
https://app.mrpeasy.com/....
Or easier actually, pass the data directly in the body :
curl -X POST \
-H 'Content-Type: application/json' \
-H 'api_key: xxxxxxxxxxxxx' \
-H 'access_key: xxxxxxxxxxxxx'
--data '{"custom_3338": "1654642800.0000000000"}' \
https://app.mrpeasy.com/....

How to format a JSON array in the request body of a multipart/form-data request with OpenAPI 3?

I'm trying to write the OpenAPI 3 specs for an existing endpoint. The endpoint uses Content-Type of multipart/form-data and one of the parameters accepts a JSON array string. The following curl shows an example of this endpoint working correctly:
curl -X 'POST' \
'https://testing.org/test/' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'simple=abc' \
-F 'complex=[{"key": "string", "size": 0}"]'
My OpenAPI 3 specs currently look like the following:
openapi: 3.0.3
info:
title: Simple
description: Testing
version: '1.0'
servers:
- url: 'https://testing.org'
paths:
/test/:
post:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
simple:
type: string
complex:
type: array
items:
type: object
properties:
key:
type: string
size:
type: integer
encoding:
complex:
contentType: application/json
responses:
'200':
description: OK
However, using the "test it out" functionality in swagger editor results in a request that looks like this:
curl -X 'POST' \
'https://testing.org/test/' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'simple=abc' \
-F 'complex=["{\n \"key\": \"string\",\n \"size\": 0\n}"]'
with the complex parameter not formatted correctly. If I removed the encoding portion of the specs, this is what the request looks like:
curl -X 'POST' \
'https://testing.org/test/' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'simple=abc' \
-F 'complex={
"key": "string",
"size": 0
}'
which is a JSON object but not a JSON array.
Any advice on how to format the OpenAPI 3 specs so that complex form parameter is formatted as a simple JSON array [{"key": "string", "size": 0}"]? Thank you!
Your API definition is correct. It should even work without encoding because the Content-Type for objects and arrays of objects is application/json by default.
The problem is that Swagger UI and Swagger Editor do not properly support JSON in multipart bodies yet. Here are the related issues you can track:
Encoding attribute is not respected on the request
Generated CURL seems wrong for mime/multipart uploads that have JSON parts - missing 'type=' option, wrong quotes
multipart/form-data should support custom content-type selection

Curl request to ansible playbook

Sample curl request.
curl -X POST \
--data '"test connection"' \
-H 'Content-type: application/json' \
-H 'Authorization: Basic asdfasdf' \
dns.com/end
Now, I'd like to send exactly the same message using curl ansible playbook.
---
- name: "Send test"
hosts: localhost
tasks:
- name: Send test
uri:
url: dns.com/end
method: POST
src: '"test connection"'
body_format: json
headers:
Content-type: "application/json"
Authorization: "Basic asdfasdf"
I'm getting an error.
You should be using the body parameter instead of src. Also, the header should be Content-Type instead of Content-type.
Just to add src is used when you want to submit the data from a file.
Solution will look something like
tasks:
- name: Send test
uri:
url: dns.com/end
method: POST
body: "test connection"
headers:
Content-Type: "application/json"
Authorization: "Basic asdfasdf"
You have mentioned body format as json and you are not passing any body to it.
You body.json file should contain something like this:
{
"name": "test connection"
}
and also you can mention status_code=201 for POST method.

(400) Bad Request when trying to send an image to my custom AutoML model via the REST API

I'm trying to implement my custom AutoML model in C# by sending images via the REST API, but I keep getting different errors.
The one I currently have is:
The remote server returned an error: (400) Bad Request.
I have taken an image and converted into a string of bytes called byteString and have created the jsonRequest object like this:
string jsonRequest = "{\"payload\":{\"image\":{\"imageBytes\":\"" + byteString + "\"},}}";
Then I'm doing a POST request like follows:
WebRequest request = WebRequest.Create(#"https://automl.googleapis.com/v1beta1/projects/PROJECT_ID/locations/us-central1/models/MODEL_ID:predict");
request.Method = "POST";
request.ContentType = "application/json";
request.Headers.Add("Authorization", "Bearer GCLOUD_ACCESS_TOKEN");
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(jsonRequest);
}
Then when it hits request.GetResponse(); if gives me the above error with no other information.
For reference, these are the snippets taken from the bottom of the PREDICT page on my custom AutoML model:
request.json:
{
"payload": {
"image": {
"imageBytes": "YOUR_IMAGE_BYTE"
},
}
}
Execute the request:
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
https://automl.googleapis.com/v1beta1/projects/PROJECT_ID/locations/us-central1/models/MODEL_ID:predict -d #request.json
Thanks guys, been stuck on this for a while.
Can you try to base64 the byte string? This is mentioned here.
In my use case, I share my vision model to my colleagues by creating a service account for them with the right role and give them this URL for prediction:
curl -X POST -H "Authorization: Bearer add_access_token " -H "Content-Type: application/json" https://automl.googleapis.com/v1beta1/projects/id_project/locations/us-central1/models/:model_idpredict -d #path_of_file_image_in_base64
I was able to solve this with RestSharp(https://www.nuget.org/packages/RestSharp) library
Example:
var client = new RestClient("https://automl.googleapis.com/v1beta1/projects/{project-id}/locations/us-central1/models/{model-id}:predict":
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", $"Bearer {Access-Token}");
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"payload\":{\"image\":{\"imageBytes\":\"{Image-Base64}""}}}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Grails - JSON param request not passing to controller

I would like to pass a JSON to my requete.
But not possible to find the JSON.
#Secured(['ROLE_STUDENT'])
def validate() {
println params
println request.JSON
}
Result :
[controller:student, action:validate, id:2345444]
[:]
URL :
curl -i -H "Content-Type: application/json" -X POST -d '{"studentScores":[{"id":"2","score":"17"}],"comment":"good"}' 'http://localhost:8080/myapp/studient/2345444/validate' -H 'Cookie: JSESSIONID=3CCDC701553A2208428BB7135DDA5546'
I tried with GET and POST, and with à JQuery
$.ajax({
url: urlSubmit,
type: 'POST',
data: JSON.stringify(student),
contentType:"application/json; charset=utf-8",
dataType: "json"
});
Grails 2.4.4
Java 8 (compliance level java 7)
Tomcat 8
Some plugins :
spring-security-core:2.0-RC4
spring-security-facebook:0.16.2
spring-security-oauth2-provider:2.0-RC2
Need your help
See this: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html (9.3 GET).
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI
Request-URI being the important part here. There is no concept of body data in a GET requests.
So, change to POST and your request should work.
For first u have an error in your url in curl :)
http://localhost:8080/myapp/STUDIENT/2345444/validate
try this code
def json = JSON.stringify(params)
but I don't sure.