400 Bad Request upload jar to Apache Flink - c#

I'm am getting a 400 Bad Request using the Flink RestApi to upload a jar file to the endpoint "/jars/upload" with c#, the endpoint definition is
The jar must be sent as multi-part data. Make sure that the "Content-Type" header is set to "application/x-java-archive", as some http libraries do not add the header by default. Using 'curl' you can upload a jar via 'curl -X POST -H "Expect:" -F "jarfile=#path/to/flink-job.jar" http://hostname:port/jars/upload'.
And the documentation i'm following is: https://nightlies.apache.org/flink/flink-docs-release-1.16/docs/ops/rest_api/.
This is the error i always get
org.apache.flink.runtime.rest.handler.RestHandlerException: Request did not match expected format EmptyRequestBody.
I've tried that endpoint using Postman and Python and it works ok but not using c#. This is the code im trying with
var stream = File.OpenRead(jarPath);
var flinkClient = new HttpClient()
{
BaseAddress = new Uri("xxxx"),
Timeout = TimeSpan.FromSeconds(3000)
};
var content = new MultipartFormDataContent()
{
{ new StreamContent(stream), "jarfile", "test-0.0.2-SNAPSHOT.jar"},
};
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-java-archive");
var response = await flinkClient.PostAsync("jars/upload", content);
var resultContent = await response.Content.ReadAsStringAsync();
I've also tried using the package RestClient with the same result

Related

glitch.com project can't be called with c#

I am writing this question in context of glitch.com projects.
so, i made a test project(asp.net .net6 webapi) in glitch.com which returns your ip address. The link to the webpage is https://ror-test.glitch.me/getip . It runs perfectly fine and returns response accurately when called from a browser. Now, I want to access this project from c# client (to be precise unity3d) however i am unable to access it.
My first try was to use httpclient.getstringasync-
Code-
HttpClient client = new HttpClient();
string response = await client.GetStringAsync(url);
System.Console.WriteLine(response);
Output-
Unhandled exception. System.Net.Http.HttpRequestException: Response status code does not indicate success: 403 (Forbidden).
In my second try i used httpclient.getasync
Code-
HttpClient client = new HttpClient();
var response = await client.GetAsync(url);
Output-
Response - https://jpst.it/348Ik
Response.Content - https://jpst.it/348LS
Also just to say that my app is working perfectly fine when i call the project from nodejs it works perfectly-
Code -
var url = "https://ror-test.glitch.me/getip";
var XMLHttpRequest = require("xhr2");
var xhr = new XMLHttpRequest();
console.log("starting");
xhr.open("GET", url);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(xhr.status);
console.log(xhr.responseText);
}};
xhr.send();
Output -
starting
200
your ip: xx.xx.xxx.xx
In place of xx.xx.xxx.xx my real ip which i have cross checked with https://whatismyipaddress.com/ is coming. so i am sure problem is with c# client.
Plz help me or any other way i can call it from c# client(precisely unity3d).
You need to pass User-Agent request header.
HttpClient client = new HttpClient();
//add user agent
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "fake");
var response = await client.GetAsync(url);

API PUT /marketing/contacts/imports with restsharp

Due to internal reason, I need to recode my servlet from Java to c#.
I am trying to upload a CSV file using the API PUT /marketing/contacts/imports with restsharp.
I cannot manage to send the file properly.
Code Snippet
Please fine below my java piece of code working:
File file = new File(CSV);
byte[] data;
try {
data = Files.readAllBytes(file.toPath());
HttpResponse<String> response2 = Unirest.put(URLSengrid)
.header(processSendgridHeader(headerFromSengrid).get(0), processSendgridHeader(headerFromSengrid).get(1))
//("x-amz-server-side-encryption", "aws:kms")
.body(data)
.asString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And here the non working c# code:
byte[] file = System.IO.File.ReadAllBytes(testPath);
var clientSecondCall = new RestClient(URLSendgrid);
var requestSecondCall = new RestRequest(Method.PUT);
requestSecondCall.AddHeader("content -type", "application/json");
requestSecondCall.AddHeader("x-amz-server-side-encryption", "aws:kms");
requestSecondCall.AddParameter("application/json", "{"file_type":"csv","field_mappings":["e1_T","e2_T","_rf2_T","e4_T","e5_T","e12_T","e13_T","e14_T","e15_T","e16_T"]}", ParameterType.RequestBody);
requestSecondCall.AddFile("file", file, testPath);
I spent a long time looking for an answer without success. Any help would be appreciated
Technical details:
sendgrid-csharp version: 9.*
csharp version: v4.0.303190
I believe the problem is the way you send the file in your c# code.
The Java code is clearly using the Body of the request, while the c# code is using RestSharp.
Restsharp is sending files in as a Multipart form, which your server is probably not qualified to handle.
I would recommend using HttpClient object:
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage();
request.Method = HttpMethod.Put;
request.RequestUri = new Uri( "Your Url");
request.Content = new StringContent(File.ReadAllText(yourFilePath));
request.Headers.Add("your header name", "your header value");
var response = client.SendAsync(request).Result;

How to replicate Postman POST request in C#

I'm fairly new to .NET's HTTPClient class, hence kindly excuse if I sounded noob. I'm tryin to replicate Postman's POST request in C# .Net and written following code. However I'm not getting any response but StatusCode: 404. Could someone assist understanding where I'm going wrong?
Also I'd like to understand, how do set Body in following code.
var httpClient = new HttpClient
{
BaseAddress = new Uri("https://testURL.com"),
Timeout = TimeSpan.FromMinutes(10)
};
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("audio/wav"));
httpClient.DefaultRequestHeaders.Add("Authorization", "Basic ldjfdljfdlfjdsjfdsl");
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("model", "Test"),
});
var result = httpClient.PostAsync("api/v1/recognize", content).Result;
Here is what I'm doing in Postman and it works:
"Params" in Postman refers to query parameters which are appended to the URL. You'll see that the URL in Postman contains the parameters you added in the "Params" tab:
However, it seems those are just dummy values you've entered so perhaps you don't need them? In any case, the way you add query parameters to the request for HttpClient is a little different as it needs to be added to the URL.
After that you also need to add the audio file as content to your request. At the moment you're setting the "Accept" header to "audio/wav" but you probably want to set the "Content-Type" header instead (or are you expecting a WAV file to be returned in the response too?).
As far as I can see this is what you're missing:
using (var httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromMinutes(10);
// Set request headers
httpClient.DefaultRequestHeaders.Add("Authorization", "Basic ldjfdljfdlfjdsjfdsl");
// Set query parameters
var uriBuilder = new UriBuilder("https://testURL.com/api/v1/recognize");
uriBuilder.Query = "model=Test";
// Build request body
// Read bytes from the file being uploaded
var fileBytes = File.ReadAllBytes(wavFilePath);
// Create request content with metadata/headers to tell the
// backend which type of data (media type) is being uploaded
var byteArrayContent = new ByteArrayContent(fileBytes);
byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("audio/wav");
// Wrap/encode the content as "multipart/form-data"
// See example of how the output/request looks here:
// https://dotnetfiddle.net/qDMwFh
var requestContent = new MultipartFormDataContent
{
{byteArrayContent, "audio", "filename.wav"}
};
var response = await httpClient.PostAsync(uriBuilder.Uri, requestContent);
}
I haven't tested this of course against your application, but it should be something along the lines of this. It might be that the backend doesn't expect "multipart/form-data" and just needs the "audio/wav". I can't see the output headers in your Postman screenshots, but if so, you can use byteArrayContent directly instead of wrapping it in MultipartFormDataContent.
Note: Don't use httpClient.PostAsync(...).Result. If you want to use the asynchronous method, you should await it. Depending on your code, using Result might give you problems if you're not careful. And remember to dispose the HttpClient after use (easiest solution is to use a using statement). If you plan on reusing the HttpClient for more requests, you can avoid disposing it until you're done.

InvalidSignatureException with AWS Kinesis Video Stream C#

I am attempting to execute my own HTTP signed request since there is no SDK in C# for the PutMedia API for the AWS Kinesis Video Stream, but I am getting the following error message:
StatusCode: 403, ReasonPhrase: 'Forbidden'
x-amzn-ErrorType: InvalidSignatureException:http://internal.amazon.com/coral/com.amazon.coral.service/
Here is a gist of what my code looks like:
var streamName = "audio-stream-test";
var service = "kinesisvideo";
var endpoint = GetPutMediaEndpoint(streamName);
var host = GetHostFromEndpoint(endpoint);
var region = GetRegionFromEndpoint(endpoint);
var t = DateTime.UtcNow;
var canonical_uri = $"{endpoint}/putMedia";
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(canonical_uri));
httpRequestMessage.Headers.Add("connection", "keep-alive");
httpRequestMessage.Headers.Add("host", host);
httpRequestMessage.Headers.Add("Transfer-Encoding", "chunked");
httpRequestMessage.Headers.Add("user-agent", "AWS-SDK-KVS/2.0.2");
httpRequestMessage.Headers.Add("x-amzn-fragment-acknowledgment-required", "1");
httpRequestMessage.Headers.Add("x-amzn-fragment-timecode-type", "ABSOLUTE");
httpRequestMessage.Headers.Add("x-amzn-producer-start-timestamp", (t - DateTime.MinValue).TotalMilliseconds.ToString());
httpRequestMessage.Headers.Add("x-amzn-stream-name", streamName);
httpRequestMessage.Headers.Add("x-amz-security-token", sessionToken);
var byteArray = File.ReadAllBytes(filePath);
var content = new ByteArrayContent(byteArray);
httpRequestMessage.Content = content;
var httpClient = new HttpClient();
var aws4RequestSigner = new AWS4RequestSigner(accessKey, secretAccessKey);
var signedHttpRequestMessage = aws4RequestSigner.Sign(httpRequestMessage, service, region).Result;
var httpResponseMessage = httpClient.SendAsync(signedHttpRequestMessage);
Screenshot of Error
I am using the Aws4RequestSigner NuGet package to sign the request. Any ideas what I am doing wrong here? Has anyone tried to use the AWS Kinesis Video Stream with C#/.NET successfully?
Two potential issues with the pseudo-code.
If using session token then the request signing should include the session token as well not only access key/secret access key combination.
The body of the PutMedia is "endless" as it streams out as a realtime stream. As such, the data shouldn't be included in the signature calculation.
This is answer to your question "the actual "content" is not being added to the stream. I see the Put Connection from KVS but no data added".
After you get 200 by setting http headers properly for the signing with below code, you need to have your content set in signedHttpRequestMessage.
var httpResponseMessage = httpClient.SendAsync(signedHttpRequestMessage);

Can JSON be sent with HttpClient in C# using the PATCH verb?

I am working with an API that requires a call with the PATCH verb. I am trying to issue a request using the HttpClient object in C#. The request sends, however the JSON is not present in the body. Instead it is blank. Relevant code below.
var patch = new HttpMethod("PATCH");
var http = new HttpRequestMessage(patch, "https://apiendpoint");
var content = new StringContent(json, Encoding.UTF8, "application/json");
http.Content = content;
var result = client.SendAsync(http).Result;
This is my first time using SendAsync, so perhaps I am missing something else that needs to be set on the HttpRequestMessage?

Categories