I have an issue with using Method.Post on my flutter app using http dart library. It seems that when I tried to post data from my WebAPI it gaves me a StatusCode 415. See my code below:
Code Login:
Future<User> login(User user) async {
print(URLRequest.URL_LOGIN);
return await _netUtil.post(Uri.encodeFull(URLRequest.URL_LOGIN), body: {
'username': user.username,
'password': user.password
}, headers: {
"Accept": "application/json",
}).then((dynamic res) {
print(res.toString());
});
}
Code NetworkUtils:
Future<dynamic> post(String url, {Map headers, body, encoding}) async {
return await http
.post(url, body: body, headers: headers, encoding: encoding)
.then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || json == null) {
throw new Exception('Error while fetching data.');
}
return _decoder.convert(res);
});
}
Does anyone knew whats going on my code?
Try adding this new header:
headers: {
"Accept": "application/json",
"content-type":"application/json"
}
UPDATE
Ok now you need to send json data, like this :
import 'dart:convert';
var body = jsonEncode( {
'username': user.username,
'password': user.password
});
return await _netUtil.post(Uri.encodeFull(URLRequest.URL_LOGIN), body: body, headers: {
"Accept": "application/json",
"content-type": "application/json"
}).then((dynamic res) {
print(res.toString());
});
}
#Alvin Quezon
I met the same error as yours and fix it, please see below.
[Error]
StateError (Bad state: Cannot set the body fields of a Request with content-type "application/json".)
[Reason]
when you use the Flutter plug 'http.dart' method 'http.post()', you should read the document in detail below (note the black fonts):
Sends an HTTP POST request with the given headers and body to the given URL.
[body] sets the body of the request. It can be a [String], a [List<int>] or
a [Map<String, String>]. If it's a String, it's encoded using [encoding] and
used as the body of the request. The content-type of the request will
default to "text/plain".
If [body] is a List, it's used as a list of bytes for the body of the
request.
If [body] is a Map, it's encoded as form fields using [encoding]. The content-type of the request will be set to "application/x-www-form-urlencoded"; this cannot be overridden.
[encoding] defaults to [utf8].
For more fine-grained control over the request, use [Request] or
[StreamedRequest] instead.
Future<Response> post(Uri url,
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
_withClient((client) =>
client.post(url, headers: headers, body: body, encoding: encoding));
[Solution]
So just encode your body as a string ,then you can set the header 'content-type' as 'application/json'.
see the codes of #diegoveloper answered!
Related
I'm trying to create a custom IBM AppID Management Api interface in my application.
In order to do that, I'm using IBM IAM Token Manager library to get an IAM access token.
const itm = require('#ibm-functions/iam-token-manager')
const m = new itm({
"iamApiKey": apiKey
})
m.getAuthHeader().then(token => {
console.log("this one won't work", token)
}
var headers =
{
'accept': 'application/json',
'Authorization': token,
'Content-Type': 'application/json'
};
var options =
{
url: replacedIssUrl+"/users",
method: 'POST',
headers: headers,
body: dataString
};
function callback(error, response, body) {
console.log(response)
if (!error && response.statusCode == 200) {
console.log(body); //returns "body: "Forbidden"
}
}
request(options, callback)
Whenever I try to pre-register a user with the library's generated token, the callback returns Status 403 - Forbidden, but if it gets the IAM Access token directly through ibmcloud shell (ibmcloud iam oauth-tokens), it works fine.
Does anybody have any clue why this is happening? I know for a fact that the IAM Token Manager library generated access token is working, because I'm using it to get the user ID on the same code.
When something is wrong with my Access Token, it usually returns "Unauthorized", not "Forbidden".
I have no clue why this is happening.
Thanks in advance.
When passing an IAM token in the headers, App ID expects it to be preceded by the "Bearer " string :
var headers =
{
'accept': 'application/json',
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
};
Sending request from javascript to rails and providing the Authorization header with a token always shows up as empty headers on my rails API.
I have the follow piece of base code for all my API controllers:
module Api
class BaseController < ActionController::API
before_action :require_login
private
def require_login
unless signed_in?
head :unauthorized
end
end
def signed_in?
current_user.present?
end
def current_user
if request.headers['Authorization'].present?
User.find_by(token: request.headers['Authorization'])
else
nil
end
end
end
end
Doing my fetch request on javascript side like this:
fetch(`/api/clients?page=${page}`, {
headers: {
Accept: "application/json",
"Content-Type": "application/json",
'Authorization': AUTH_TOKEN
},
credentials: 'same-origin',
})
Fetching the value Authorization from request.headers always comes up as nil.
Anyone knows what might be going wrong?
Since you're using the Fetch() library, you can use the new Request() object which helps you customize your configurations.
// https://developer.mozilla.org/en-US/docs/Web/API/Request/Request
var myHeaders = new Headers({
"Content-Type": "application/json",
'Authorization': AUTH_TOKEN
});
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request(`/api/clients?page=${page}, myInit);
fetch(myRequest).then(function(response) {
...
});
I had the same issue with Axios and it turns out I was using a get request with headers and params wrongly.
const params = { id: "ghjfsd7634" };
const headers = {
headers: {
"Content-Type": "application/json",
Authorization: token,
},
};
axios
.get(url, params, headers)
.then(function foo(response) {
handleResponse(response.data);
})
.catch(function foo(error) {
console.log("GET Resource Error");
console.log(error);
});
Correct way: Params and headers in get requests are passed differently compared to post, put etc. requests. Axios takes the entire config in the second argument, not a list of config objects. Put the params inside the config, and pass the entire object as the second argument:
const params = { id: "ghjfsd7634" };
const headers = {
"Content-Type": "application/json",
Authorization: token,
};
const config = { headers, params };
await axios
.get(url, config)
.then(function foo(response) {
handleResponse(response.data);
})
.catch(function foo(error) {
console.log("GET Resource Error");
console.log(error);
});
I try to consume a service via post whit angular2. This my code:
var m_dataRequest = this.buildLoginUserPasswordRequest(password, key);
let headers = new Headers({
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'es-ES,es;q=0.8,en;q=0.6',
'Content-Type': 'application/x-www-form-urlencoded',
});
let options = new RequestOptions({ headers: headers });
let body = new URLSearchParams();
body.set("message", JSON.stringify(m_dataRequest));
body.set("webService", "authService");
return this.http
.post(this.Url, body.toString(), options)
.toPromise()
.then(this.extractData)
.catch(this.handleError);
private buildLoginUserPasswordRequest(password:string, key:string): any {
var m_dataRequest = {
"ser:nativeAppAuth": {
"-xmlns:ser": "http://services.mobileappbc.ws.todo1.com/",
"password": this.utilService.buidRSAPass(password, t1Assertion),
"key": key,
"deviceInfo": this.utilService.getDeviceInfo()
}
};
return m_dataRequest;
}
The Content-type is application/x-www-form-urlencoded because the backend need the info of this way.
My problem is the character ":" is not convert to equivalent urlencoded %3A+.
this cause a problem in my backend service.
any Suggestion for solve this?
Thanks!
Json.stringify does not uri encode data because it can handle it.
You need to use uriencode()
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
Currently I have a problem with an Angular2 and RoR5 API. I'm trying to save an object to the API Server, but this doesn't work.
Here is my Angular2 Code for the service:
createFrame(frameData) {
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify({frame: frameData});
return this.http.post(this.frameURL, body, headers).map((res: Response) => res.json());
}
The request is made by my browser and I can see the JSON Data:
But RoR is not able to get the POST Data.
[1] pry(#<Api::V1::FramesController>)> params
=> <ActionController::Parameters {"format"=>:json, "controller"=>"api/v1/frames", "action"=>"create"} permitted: false>
[2] pry(#<Api::V1::FramesController>)>
Can someone tell me, what's wrong?
In your case, you set the content type for form data and you send some content with the JSON format.
Either you use send form data or JSON content.
Form data
createFrame(frameData) {
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
let form = new URLSearchParams();
form.set('param1', 'some value');
let body = form.toString();
return this.http.post(this.frameURL, body, headers).map((res: Response) => res.json());
}
JSON data
createFrame(frameData) {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
let form = new URLSearchParams();
form.set('param1', 'some value');
let body = form.toString();
return this.http.post(this.frameURL, body, headers).map((res: Response) => res.json());
}
The problem might be related to CORS (Cross Origin Resource Sharing)
Thy to enable in your application -->
Enabling cors Rails5
Good luck
ReactNative provide me with fetch to send a httpRequest.The attribute of body includes my parameters which are to send to the server.But I can't get the parameters on my server.My codes are here:
fetch(`${keys.api}/login`,
{
method: 'POST',
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}
).then((response) => {
if(response._bodyText == 'success') {
this.props.resetToRoute({
name: '主页',
component: Main,
hideNavigationBar: true,
});
} else {
this.cancelLogin();
}
}).catch((error) => {
console.warn(error);
this.cancelLogin();
});
And the console in my J2EE Web Server prints the message:
The httpRequest message
There is no parameter in my httpRequest(In other words,The body can not deliver any parameters),I need help.
It's dangerous to show my username and password in the url.
i have met the problem twice on jetty-8.1 on different condition
first ,you should know that it has nothing to do with react-native
fetch put the data in body to header "payload" when the client made a request.i thought jetty-8.1 does not support get data from the payload header
,change the way
Getting request payload from POST request in Java servlet will be helpful
or maybe use the websockt or XMLhttpRequest object to send a request
// Read from request
StringBuilder buffer = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String data = buffer.toString()