I want to add a body to my delete http request but it seems that the http pakage doesnt accept it
http.delete('${config.basicUrl}removeFavorite', body: json.encode(requestBody))
is there any solution for this ?
final client = http.Client();
try {
final response = await client.send(
http.Request("DELETE", Uri.parse("${config.basicUrl}removeFavorite"))
..headers["authorization"] = "Bearer $bearer"
..body = "...");
//
} finally {
client.close();
}
Related
Just new to ms graph and also to .net.
I'm trying to write a method that deletes a notification subscription. The code itself seems to work. But i need to know how to look up the actual return code from the upstream API instead of just sending back a 204.
Here's the code:
[Route("msgraphnotification/{subscriptionId}")]
[HttpDelete]
[AllowAnonymous]
public async Task<Int> delete(string subscriptionId)
{
try{
GraphServiceClient graphClient = await getAuthToken();
await graphClient.Subscriptions["{subscription-id}"]
.Request()
.DeleteAsync();
return 204; // this is what I want to fix.
}
catch(Exception ex){
Console.Write(ex);
return 404;
}
}
If you really need to know the response code you can send HTTP request with the .Net Microsoft Graph client library.
// Get the request URL for deleting a subscription
var requestUrl = client.Subscriptions["{subscription-id}"].Request().RequestUrl;
// Create the request message.
var hrm = new HttpRequestMessage(HttpMethod.Delete, requestUrl);
// Authenticate HttpRequestMessage
await client.AuthenticationProvider.AuthenticateRequestAsync(hrm);
// Send the request and get the response.
var response = await client.HttpProvider.SendAsync(hrm);
// Get the status code.
if (!response.IsSuccessStatusCode)
{
throw new ServiceException(
new Error
{
Code = response.StatusCode.ToString(),
Message = await response.Content.ReadAsStringAsync()
});
}
else
{
var statusCode = (int)response.StatusCode;
}
...
I am using this code to send http request using Dart:
var request = await httpClient.postUrl(Uri.parse(url));
Map jsonMap = {'pageSize': 10};
request.add(utf8.encode(json.encode(jsonMap)));
request.headers.set('content-type', 'application/json');
var response = await request.close();
if (response.statusCode == HttpStatus.OK) {
}
but it shows:
HttpException: HTTP headers are not mutable
why give me this tips and what should I do fix this?
You need to check HttpHeaders class page. (https://api.dart.dev/stable/2.10.5/dart-io/HttpHeaders-class.html)
HttpRequest and HttpClientResponse always have immutable headers.
HttpResponse and HttpClientRequest have immutable headers from the moment the body is written to.
request.add(utf8.encode(json.encode(jsonMap)));
This line is add Request Body so made HttpClientRequest header to immutable. So if you want to add headers, you need to do it before this line.
var request = await httpClient.postUrl(Uri.parse(url));
Map jsonMap = {'pageSize': 10};
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(jsonMap)));
var response = await request.close();
if (response.statusCode == HttpStatus.OK) {
}
I am struggling with making a http post call returning JSON in flutter. I keep getting a 500 error and I dont know what the issue is. I need to pass a username and password in the header and I think the issue is how im doing it. Here is the code.
Future<User> LoginUser(String username, String password ) async {
final response =
await http.post('http://xx.xxx.xxx.xxx/api/Login',
headers: {"Content-Type": "application/json", 'email' : username , 'password' : password });
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
return User.fromJson(json.decode(response.body));
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load user');
}
}
It wont get past the 200 check because it is getting a 500. I cant find any examples with passing 2 parameters in the header and the content type so im not sure im doing that correctly.
If we have to pass 2 arguments like key and any other data, Then follow the code(Only for Post Request)
Future<ClassType> callApi()async{
const String url="your/request/to/post/link/url";
const Uri=Uri.parse(url);
Map passValues={'token':'yOuRtOkEnkEy','user_id':'123456789'};
var body = json.encode(token);
var response;
try {
response = **await** http.post(
uri,
headers: {'Content-Type': 'application/json'},
body: body,
);
} catch (e) {
print(e);
}
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
print(jsonMap);
} else {
print('API FAILED');
}
return response;
}
I'm currently trying to access a Web API in Flutter that requires a JWT access token for authorization. The access token expires after a certain amount of time.
A new access token can be requested with a separate refresh token. Right now this access token refresh is performed as soon as a request returns a 401 response. After that, the failed request should be retried with the new access token.
I'm having trouble with this last step. It seems like a http.BaseRequest can only be sent once. How would I retry the http request with the new token?
As suggested in the dart http readme, I created a subclass of http.BaseClient to add the authorization behavior. Here is a simplified version:
import 'dart:async';
import 'package:http/http.dart' as http;
class AuthorizedClient extends http.BaseClient {
AuthorizedClient(this._authService) : _inner = http.Client();
final http.Client _inner;
final AuthService _authService;
Future<http.StreamedResponse> send(http.BaseRequest request) async {
final token = await _authService.getAccessToken();
request.headers['Authorization'] = 'Bearer $token';
final response = await _inner.send(request);
if (response.statusCode == 401) {
final newToken = await _authService.refreshAccessToken();
request.headers['Authorization'] = 'Bearer $newToken';
// throws error: Bad state: Can't finalize a finalized Request
final retryResponse = await _inner.send(request);
return retryResponse;
}
return response;
}
}
abstract class AuthService {
Future<String> getAccessToken();
Future<String> refreshAccessToken();
}
Here is what I came up with so far, based on Richard Heap's answer: To resend a request, we have to copy it.
So far I was not able to come up for a solution for stream requests!
http.BaseRequest _copyRequest(http.BaseRequest request) {
http.BaseRequest requestCopy;
if(request is http.Request) {
requestCopy = http.Request(request.method, request.url)
..encoding = request.encoding
..bodyBytes = request.bodyBytes;
}
else if(request is http.MultipartRequest) {
requestCopy = http.MultipartRequest(request.method, request.url)
..fields.addAll(request.fields)
..files.addAll(request.files);
}
else if(request is http.StreamedRequest) {
throw Exception('copying streamed requests is not supported');
}
else {
throw Exception('request type is unknown, cannot copy');
}
requestCopy
..persistentConnection = request.persistentConnection
..followRedirects = request.followRedirects
..maxRedirects = request.maxRedirects
..headers.addAll(request.headers);
return requestCopy;
}
You can't send the same BaseRequest twice. Make a new BaseRequest from the first one, and send that copy.
Here's some code (from io_client) to 'clone' a BaseRequest.
var copyRequest = await _inner.openUrl(request.method, request.url);
copyRequest
..followRedirects = request.followRedirects
..maxRedirects = request.maxRedirects
..contentLength = request.contentLength == null
? -1
: request.contentLength
..persistentConnection = request.persistentConnection;
request.headers.forEach((name, value) {
copyRequest.headers.set(name, value);
});
I'm trying to add CORS headers to incoming requests but I've noticed that app.response.headers is an immutable map and app.request.response doesn't exist even though it appears in the documentation examples. So, to the OPTIONS request I'm replying using a new Shelf response, but I can't find a way to add any new headers to the response of the actual request. Any ideas?
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
// app.request.response is not available
app.request.response.headers.add('Access-Control-Allow-Origin', '*');
app.chain.next();
}
}
I found the fix in the first piece of code inside the Interceptor documentation...:)
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
app.chain.next(() => app.response.change(headers: HEADERS));
}
}
app.chain.next() can take a callback as argument, which is expected to return a Response object. In this case app.response.change() returns a response with the correct headers.