using OpenTSDB HTTP api in .NET : 400 Bad Request - c#

I'm trying to use .net to put datapoints in OpenTSDB, using the HTTP /api/put API.
I've tried with httpclient, webRequest and HttpWebRequest. The outcome is always 400 - bad request: chunked request not supported.
I've tried my payload with an api tester (DHC) and works well.
I've tried to send a very small payload (even plain wrong, like "x") but the reply is always the same.
Here's one of my code instances:
public async static Task PutAsync(DataPoint dataPoint)
{
try
{
HttpWebRequest http = (HttpWebRequest)WebRequest.Create("http://127.0.0.1:4242/api/put");
http.SendChunked = false;
http.Method = "POST";
http.ContentType = "application/json";
Encoding encoder = Encoding.UTF8;
byte[] data = encoder.GetBytes( dataPoint.ToJson() + Environment.NewLine);
http.Method = "POST";
http.ContentType = "application/json; charset=utf-8";
http.ContentLength = data.Length;
using (Stream stream = http.GetRequestStream())
{
stream.Write(data, 0, data.Length);
stream.Close();
}
WebResponse response = http.GetResponse();
var streamOutput = response.GetResponseStream();
StreamReader sr = new StreamReader(streamOutput);
string content = sr.ReadToEnd();
Console.WriteLine(content);
}
catch (WebException exc)
{
StreamReader reader = new StreamReader(exc.Response.GetResponseStream());
var content = reader.ReadToEnd();
}
return ;
}
where I explicitly set to false the SendChunked property.
note that other requests, like:
public static async Task<bool> Connect(Uri uri)
{
HttpWebRequest http = (HttpWebRequest)WebRequest.Create("http://127.0.0.1:4242/api/version");
http.SendChunked = false;
http.Method = "GET";
// http.Headers.Clear();
//http.Headers.Add("Content-Type", "application/json");
http.ContentType = "application/json";
WebResponse response = http.GetResponse();
var stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
string content = sr.ReadToEnd();
Console.WriteLine(content);
return true;
}
work flawlessly.
I am sure I am doing something really wrong.
I'd like to to reimplement HTTP in Sockets from scratch.

I've found a solution I'd like to share here.
I've used wireshark to sniff my packets, and I've found that this header is added:
Expect: 100-continue\r\n
(see 8.2.3 of https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html)
This is the culprit. I've read the post http://haacked.com/archive/2004/05/15/http-web-request-expect-100-continue.aspx/ by Phil Haack, and found that HttpWebRequest puts that header by default, unless you tell it to stop. In this article I've found that using ServicePointManager I can do just this.
Putting the following code on top of my method, when declaring the http object, makes it work very well, and solves my issue:
var uri = new Uri("http://127.0.0.1:4242/api/put");
var spm = ServicePointManager.FindServicePoint(uri);
spm.Expect100Continue = false;
HttpWebRequest http = (HttpWebRequest)WebRequest.Create(uri);
http.SendChunked = false;

Related

Getting 400 (bad request) when trying to send a message to slack with webhook URL

I'm trying to send a message to a slack channel in C#. with http request, using Webhook url.
In the get response line' I'm getting 400- bad request.
My function:
public void SendSlackAlert(string message, string slackUrl)
{
try
{
var content = $"{{\r\n\"text\":\"{Context}\r\n{message} \"\r\n}}";
if (string.IsNullOrWhiteSpace(slackUrl))
{
return;
}
var httpRequest = WebRequest.Create(slackUrl) as HttpWebRequest;
httpRequest.Method = "POST";
httpRequest.Accept = "application/json";
httpRequest.Timeout = Convert.ToInt32(TimeSpan.FromDays(1).TotalMilliseconds);
var bytesToSend = Encoding.UTF8.GetBytes(content);
httpRequest.ContentType = "application/json;charset=utf-8";
httpRequest.ContentLength = bytesToSend.Length;
using (var requestStream = httpRequest.GetRequestStream())
requestStream.Write(bytesToSend, 0, bytesToSend.Length);
var httpResponse = httpRequest.GetResponse() as HttpWebResponse;
using (var responseReader = new StreamReader(httpResponse.GetResponseStream(), Encoding.UTF8))
{
responseReader.ReadToEnd();
}
}
catch (Exception ex)
{
// return "Error";
}
}
I am transferred to catch with the error, in this line:
var httpResponse = httpRequest.GetResponse() as HttpWebResponse;
would greatly appreciate any attempt to help.
Thank you!
I saw elsewhere that having the encoding set can cause issues with the Slack API.
Instead of setting the Content-Type header along with an encoding, try only setting the Content-Type header to application JSON.
Replace this line:
httpRequest.ContentType = "application/json;charset=utf-8";
With this line:
httpRequest.Headers.Add(HttpRequestHeader.ContentType, "application/json");

HttpWebRequest.getResponse() returning NULL

I am attempting to create a console app that sends a WebRequest to a website so that I can get some information back from it in JSON format. Once I build up the request and try to get response I just want to simply print out the data, but when I call httpWebRequest.getResponse() it returns NULL.
I have tried multiple other methods of sending the data to the the url but those are all giving me like 404, or 400 errors, etc. This method at least isn't giving me any error, just a NULL.
Here is a snapshot of the documentation I am using for the API (albeit the docs aren't complete yet):
Here is the console app code that I have right now:
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.remot3.it/apv/v27/user/login");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("developerkey", "***KEY***");
using (var streamWriter = new
StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new
{
email = "***EMAIL***",
password = "***PASSWORD***"
});
Console.WriteLine(json);
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
Console.ReadLine();
}
}catch(Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
Console.ReadLine();
}
Expected output is some JSON data, but I am getting a NULL back from getResponse().
Try to serialize the credential in your form and for header send as parameter for this class.
Check below for my code. It is not 100 % fit to your requirement, but atleast it will help to get through your logic.
Here is what I get Json Response from this code. Its work Perfect. Please remember to add timeout option on your webrequest and at the end close the streamreader and stream after completing your task. please check this code.
public static string httpPost(string url, string json)
{
string content = "";
byte[] bs;
if (json != null && json != string.Empty)
{
bs = Encoding.UTF8.GetBytes(json);
}
else
{
bs = Encoding.UTF8.GetBytes(url);
}
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.Method = "POST";
if (json != string.Empty)
req.ContentType = "application/json";
else
req.ContentType = "application/x-www-form-urlencoded";
req.KeepAlive = false;
req.Timeout = 30000;
req.ReadWriteTimeout = 30000;
//req.UserAgent = "test.net";
req.Accept = "application/json";
req.ContentLength = bs.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
reqStream.Flush();
reqStream.Close();
}
using (WebResponse wr = req.GetResponse())
{
Stream s = wr.GetResponseStream();
StreamReader reader = new StreamReader(s, Encoding.UTF8);
content = reader.ReadToEnd();
wr.Close();
s.Close();
reader.Close();
}
return content;
}

c# How to send HTTP command as this - http://192.168.10.1/api/control?alert=101002

I have this hardware from Patlite,
This hardware has an HTTP command control function, for example, if I copy the url "http://192.168.10.1/api/control?alert=101002" to chrome in my computer, it will activate the hardware as needed.
I want to send the command from my code.
I tried this code with no luck:
System.Net.ServicePointManager.Expect100Continue = false;
WebRequest request = WebRequest.Create("http://10.0.22.222/api/control");
request.Method = "post";
request.ContentType = "application/x-www-form-urlencoded";
string postData = "alert=101002";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
WebResponse response = request.GetResponse();
There is a picture from the manual:
Thanks
You need to create a webrequest instance for this.
WebRequest request = WebRequest.Create("http://192.168.10.1/api/control?alert=101002");
WebResponse response = request.GetResponse();
You may need to set some properties as request method and credentials for this to work.
See this:
https://msdn.microsoft.com/en-us/library/456dfw4f(v=vs.100).aspx
public static string Get(string url, Encoding encoding)
{
try
{
var wc = new WebClient { Encoding = encoding };
var readStream = wc.OpenRead(url);
using (var sr = new StreamReader(readStream, encoding))
{
var result = sr.ReadToEnd();
return result;
}
}
catch (Exception e)
{
//throw e;
return e.Message;
}
}
like this code use the url "http://192.168.10.1/api/control?alert=101002" to send get request.Good luck!

Expecting JSON/XML data in Webapi

when i request one webapi request, i got error like Expecting JSON/XML data
try
{
string oRequest = _xml.UpdateInvereqxml(UserName, Password,OTAhotelid, Invy);
string uri = #"service/update";
System.Net.WebRequest req = System.Net.WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "text/xml";
System.IO.StreamWriter writer = new System.IO.StreamWriter(req.GetRequestStream());
writer.WriteLine(oRequest);
writer.Close();
System.Net.WebResponse rsp = req.GetResponse();
Stream istrm = rsp.GetResponseStream();
string StreamReader = new StreamReader(istrm).ReadToEnd();
}
I suggest using HttpClient to communicate with ASP.NET Web API. The class provides many functions for working with REST service (example)
public EnumProduct Post(EnumProduct product)
{
HttpResponseMessage reponse = httpClient.PostAsJsonAsync("api/enumproducts/Post", product).Result;
if (reponse.IsSuccessStatusCode)
{
var enumProduct = reponse.Content.ReadAsAsync().Result;
return enumProduct;
}
else
return null;
}

How to mix compression and caching in HttpWebRequest?

I have a c# client talking to a cherrypy(http/rest) webservice.
The problem is i can't both turn on compression and caching at the same time.
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
By leaving out the above line I get the correct caching headers (If-None-Math,If-Modified-Since) while commenting it out gets me the compression headers (Accept-Encodig:gzip) but not the caching headers. It seems to me like a bug but maybe i'm doing something wrong.
[full code]
public static string GET(string URL)
{
string JSON;
// Create the web request
HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
HttpRequestCachePolicy cPolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Revalidate);
request.Accept = "application/json";
request.CachePolicy = cPolicy;
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Pipelined = false;
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader readerF = new StreamReader(response.GetResponseStream());
JSON = readerF.ReadToEnd();
// Console application output
//Console.WriteLine(JSON);
if (response.IsFromCache )
Console.WriteLine("Request not from cache");
}
return JSON;
}
I have implemented a workaround, see code below. I judged handling the compression easier than handling the cacheing so I implemented the compression part myself. Quite easy thanks to a blog post: HttpWebRequest and GZip Http Responses; I still think this is a bug in .net.
public static string GET(string URL)
{
string JSON;
// Create the web request
HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
HttpRequestCachePolicy cPolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Revalidate);
request.Accept = "application/json";
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
request.CachePolicy = cPolicy;
request.Pipelined = false;
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
//From http://www.west-wind.com/WebLog/posts/102969.aspx
Stream responseStream = responseStream = response.GetResponseStream();
if (response.ContentEncoding.ToLower().Contains("gzip"))
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
else if (response.ContentEncoding.ToLower().Contains("deflate"))
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
// Get the response stream
StreamReader readerF = new StreamReader(responseStream);
JSON = readerF.ReadToEnd();
}
return JSON;
}
Is this a side effect of the policy?
What happens if you just use the default policy, or other policies?
Other option is to manage the cache yourself.

Categories

Resources