Google Vision Rest API in Xamarin - rest

I'm trying to call the Google Vision REST API from a Xamarin.Forms app. I have the following code:-
private async void SendToGoogle(MediaFile file)
{
using (HttpClient client = new HttpClient())
{
string uri = "https://vision.googleapis.com/v1/images:annotate?key=API_KEY";
HttpResponseMessage response;
var stream = file.GetStream();
using (var content = new StreamContent(stream))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentLength = stream.Length;
response = await client.PostAsync(uri, content);
var resp = await response.Content.ReadAsStringAsync();
}
}
}
But this is returning me a 400 error message:
Invalid JSON payload received. Expected a value.

Related

How to return a reponse in ASP.NET Core 6 Web API JWT authentication when statuscode is 401

I developed an ASP.NET Core 6 Web API, and I'm using JWT.
I try to return a response when status code = 401, but I can not figure out.
I want to return a response as shown here:
response.ResultCode = 401;
response.ResultMessage = "Invalid token, please call Login() method."
Could you please help me?
Since you are using JWT bearer authentication, you can hook a handler to the JwtBearerEvents.OnChallenge callback like below:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
//other options....
options.Events = new JwtBearerEvents
{
OnChallenge = context =>
{
context.Response.OnStarting(async () =>
{
// Write to the response in any way you wish
await context.Response.WriteAsync("Invalid token, please call Login() method.");
});
return Task.CompletedTask;
}
};
});
I solved my problem like below.
options.Events = new JwtBearerEvents
{
OnChallenge = context =>
{
context.HandleResponse();
context.Response.StatusCode = 401;
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(new
{
ResultCode = "2",
Message = "Invalid Token"
});
return context.Response.WriteAsync(result);
},
};

Blazor Server App Multipart Form from iPhone Content Length is 0

I have this code in my WEB API that validates if the content received is multipart:
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
I do this from my Blazor Web App to POST the content:
private async Task LoadImage(InputFileChangeEventArgs e)
{
MultipartFormDataContent content;
var file = e.File;
var fileContent = new StreamContent(file.OpenReadStream());
fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
content = new MultipartFormDataContent();
content.Add(
content: fileContent,
name: "\"file\"",
fileName: file.Name);
var metadataContent = new StringContent(JsonConvert.SerializeObject(metadata));
content.Add(
content: metadataContent,
name: "\"metadata\""
);
using (HttpClient httpClient = new HttpClient())
{
var response = await httpClient.PostAsync(Configuration["backendurl"] + "/api/saveimage/save", content);
}
If I post the form from my PC browser everything works. BUT if I post the same information from an iPhone the Content-Length is 0 and the IsMimeMultipartContent() returns false in my backend.

SSE "data" field not being received by Dart http.client

I'm building a Flutter app that receives SSE from a server and translates them to specific notifications. The server is a Spring Boot app returning events containing "event:" and "data:" fields:
public void pushNotification(String username, PushEvent event) {
var emitter = emitters.get(username);
if (emitter == null) {
return;
}
try {
emitter.send(event.toSseEvent());
} catch (IOException e) {
log.debug("Could not send event for user " + username);
emitters.remove(username);
}
}
public class PushEvent {
private String type;
private Map<String, Object> body;
public SseEmitter.SseEventBuilder toSseEvent() {
return SseEmitter.event().name(type).data(body);
}
}
On the Flutter app, I use the Dart http package to open a Stream and receive the events:
Future<void> subscribe() async {
if (!_userModel.hasAuthentication()) {
return;
}
var user = _userModel.user as AuthenticatedUser;
var username = user.username;
var token = _userModel.getToken();
var uri = Uri.https(ApiUtils.API_BASE, '/api/push/subscribe/$username');
try {
var client = http.Client();
_client = client;
var request = new http.Request("GET", uri);
request.headers["Accept"] = "text/event-stream";
request.headers["Cache-Control"] = "no-cache";
request.headers["Authorization"] = token;
var response = await client.send(request);
if (response.statusCode == 200) {
_isSubscribed = true;
response.stream.toStringStream().forEach((value) {
var event = ServerEvent.parse(value);
_handleEvents(event);
}).onError((error, stackTrace) {
log.info("Connection closed");
log.info(error);
log.info(stackTrace);
unsubscribe();
}).whenComplete(() {
log.info("Connection completed");
unsubscribe();
subscribe();
});
} else {
_isSubscribed = false;
}
notifyListeners();
} catch (e) {
unsubscribe();
log.warning("Could not subscribe to notifications");
log.warning(e);
}
}
However, when I receive an event containing data from the server, the data does not show on the log:
I/flutter (14779): event:FRIEND_REQUEST
I/flutter (14779): data:
I am certain the data is being sent by the server since the React app on the same domain decodes the SSE and shows the notifications as intended:
const subscribePush = () => {
const username = sessionStorage.getItem('loggedUsername');
const token = sessionStorage.getItem('token');
var es = new EventSourcePolyfill(
'/api/push/subscribe/' + username,
{
headers: {
"Authorization": token,
}
}
);
es.onerror = () => es.close();
es.addEventListener("FRIEND_REQUEST", e => handleFriendRequestEvent(e));
es.addEventListener("FRIEND_ACCEPT", e => handleFriendAcceptEvent(e));
}
const handleFriendRequestEvent = function (event) {
const username = sessionStorage.getItem("loggedUsername");
const data = JSON.parse(event.data);
const source = data.source;
if (source !== username) {
var note = `${source} solicitou sua amizade!`;
var newNotifs = notifications.concat(note);
setNotifications(newNotifs);
setNewNotifications(newNotifications + 1);
}
}
Could something be missing from the request on the Flutter app, or is it possibly a bug?
Your implementation looks strangely similar to this one:
https://github.com/stevenroose/dart-eventsource
Take a look at the client implementation and how the response in decoded using the decoder.dart file.

CERTIFICATE_VERIFY_FAILED while using dio 3.0.10 [duplicate]

This question already has answers here:
How to solve Flutter CERTIFICATE_VERIFY_FAILED error while performing a POST request?
(25 answers)
Closed 1 year ago.
When I try to post a request I get
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: HandshakeException: Handshake error in client (OS Error:
CERTIFICATE_VERIFY_FAILED: ok(handshake.cc:354))
my code (provided in the example)
Future login() async {
final request = {
"j_username": "user1",
"j_password": "pass1",
};
final response = await _dio.post('/itim/restlogin/login.jsp', data: request);
//get cooking from response
final cookies = response.headers.map['set-cookie'];
if (cookies.isNotEmpty && cookies.length == 2) {
final authToken = cookies[1].split(';')[0]; //it depends on how your server sending cookie
//save this authToken in local storage, and pass in further api calls.
aToken = authToken;
print("authToken");
//saving this to global variable to refresh current api calls to add cookie.
print(authToken);
}
print(cookies);
//print(response.headers.toString());
}
This means your website doesn't have a valid certificate.
Please add the below code to fix this.
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient dioClient) {
dioClient.badCertificateCallback =
((X509Certificate cert, String host, int port) => true);
return dioClient;
};
Like this
Future login() async {
final request = {
"j_username": "user1",
"j_password": "pass1",
};
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient dioClient) {
dioClient.badCertificateCallback =
((X509Certificate cert, String host, int port) => true);
return dioClient;
};
final response = await _dio.post('/itim/restlogin/login.jsp', data: request);
//get cooking from response
final cookies = response.headers.map['set-cookie'];
if (cookies.isNotEmpty && cookies.length == 2) {
final authToken = cookies[1].split(';')[0]; //it depends on how your server sending cookie
//save this authToken in local storage, and pass in further api calls.
aToken = authToken;
print("authToken");
//saving this to global variable to refresh current api calls to add cookie.
print(authToken);
}
print(cookies);
Make sure you comment code when you have a valid certificate.

Why does a dart HttpClient get request take 17 sec to a localhost server?

var client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
print("Connecting to: https://192.168.100.200:8081/zoneserver/?op=1&id=$id");
Stopwatch stopwatch = new Stopwatch()..start();
var request = await client.getUrl(Uri.parse("https://192.168.100.200:8081/zoneserver/?op=1&id=$id"));
print("Got request ${stopwatch.elapsed}");
request.persistentConnection = false; // Use non-persistent connection.
var response = await request.close();
print("Got response ${stopwatch.elapsed}");
var contents = await response.transform(utf8.decoder).join();
print("Got contents ${stopwatch.elapsed}");
client.close();
print("${stopwatch.elapsed} content:$contents");
Why is this code so slow? The server is basically a hello world server and is run locally. Using Postman or a web browser the request is instant.
I am testing on Android 11 device. My suspicion is that it is the client.badCertificateCallback. But why, and is there something I can do about it?
Edit: It is the var request = await client.getUrl(Uri.parse("https://192.168.100.200:8081/zoneserver/?op=1&id=$id")); that takes 17 seconds