I'm trying to POST a Document (any file type) to a GLPI server through API REST.
Here is what I'm doing:
private void button11_Click(object sender, EventArgs e)
{
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
var rcontent = string.Empty;
// HEADERS (URL + Access Tokens)
//string _ContentType = "multipart/form-data";
string _Uri = Properties.Settings.Default.GLPI_URL + "/Document/";
client.BaseAddress = new Uri(_Uri);
//client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(_ContentType));
client.DefaultRequestHeaders.Add("Session-Token", Properties.Settings.Default.GLPI_SESSION_TOKEN);
client.DefaultRequestHeaders.Add("App-Token", Properties.Settings.Default.GLPI_APP_TOKEN);
// JSON Content (input string array with file uploaded informations)
JSON_C.DocumentAdder JSONContent = new JSON_C.DocumentAdder();
JSONContent.name = "sth";
JSONContent._filename = filebytes;
HttpContent _JSONContent = new StringContent("uploadManifest={\"input\": " + JsonConvert.SerializeObject(JSONContent).ToString() + "}", Encoding.UTF8, "application/json");
content.Add(_JSONContent);
// File Content in bytes
var fileContent = new ByteArrayContent(filebytes);
fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("_filename") { FileName = filepath };
//fileContent.ReadAsByteArrayAsync();
content.Add(fileContent);
// Request
HttpResponseMessage reponse;
var _Method = new HttpMethod("POST");
reponse = client.PostAsync(_Uri, content).Result;
// Request response
rcontent = reponse.Content.ReadAsStringAsync().Result;
textBox2.Text = reponse.ToString() + Environment.NewLine + rcontent.ToString();
}
}
}
But this is what I got in response:
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: close
Cache-Control: no-store, must-revalidate, no-cache
Date: Mon, 26 Nov 2018 12:50:09 GMT
Server: Apache/2.4.29
Server: (Ubuntu)
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Expires: Mon, 26 Jul 1997 05:00:00 GM
}
With:
["ERROR_UPLOAD_FILE_TOO_BIG_POST_MAX_SIZE","The file seems too big"]
The file I'm trying to upload is 592bytes! Max overall limit in one request is 2Mo. And post_max_size in php.ini is "8M", the same result after I changed it to "0" (for no limit at all). And then set it to 20M to match upload_max_filesize (/etc/php/7.2/apache2/php.ini).
upload_max_filesize_.. is also "20M"
If anyone finding this post and needs help, here is how i managed to succeed :
After separatly creating a "Session-Token", and using "RestSharp".
// Upload
var RSClient = new RestClient(Properties.Settings.Default.GLPI_URL);
var request = new RestRequest("Document", Method.POST);
request.AddHeader("Session-Token", Properties.Settings.Default.GLPI_SESSION_TOKEN);
request.AddHeader("App-Token", Properties.Settings.Default.GLPI_APP_TOKEN);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "multipart/form-data");
request.AddQueryParameter("uploadManifest", "{\"input\": {\"name\": \"UploadFileTest\", \"_filename\": \"GiletsJaunes.jpg\"}}");
request.AddFile("test", #"C:\path\to\File.jpg");
IRestResponse response = RSClient.Execute(request);
var content = response.Content;
textBox2.Text = textBox2.Text + Environment.NewLine + content;
Details :
I couldn't use RestSharp.Authenticator = new SimpleAuthenticator for some reasons, so i added these Auth params with AddHeader.
I couldn't use a Serialised Json string in a new StringContent, because of AddQueryParameter, so i wrote it manually.
Alleluyah.
Related
I have the following HttpeRequest Body as Text:
--batch_f1d4b121-35c3-40a0-bbbd-cb1a9f1a5f13
Content-Type: application/http; msgtype=request
POST /api/values HTTP/1.1
Host: localhost:5102
Content-Type: application/json; charset=utf-8
{"value": "Hello World"}
--batch_f1d4b121-35c3-40a0-bbbd-cb1a9f1a5f13
Content-Type: application/http; msgtype=request
PUT /api/values/5 HTTP/1.1
Host: localhost:5102
Content-Type: application/json; charset=utf-8
{"value": "Hello World"}
--batch_f1d4b121-35c3-40a0-bbbd-cb1a9f1a5f13
Content-Type: application/http; msgtype=request
DELETE /api/values/5 HTTP/1.1
Host: localhost:5102
--batch_f1d4b121-35c3-40a0-bbbd-cb1a9f1a5f13--
I tired using regex and I succeed in some and fail in others.
Dose any one manage to parse and split ?
I found that I could use MultipartSection to navigate through the batch requests:
var boundry = request.GetMultipartBoundary();
var contentTypeBoundry = request.ContentTypeBoundary();
var requests = new List<HttpRequestMessage>();
var reader = new MultipartReader(boundry, request.Body);
var section = await reader.ReadNextSectionAsync();
while (section!= null)
{
var xBodyAsText= await new StreamReader(section.Body).ReadToEndAsync();
requests.Add(xBodyAsText.ToSimpleHttpRequestMessage());
section = await reader.ReadNextSectionAsync();
}
I have got a solution from ChatGPT:
public static HttpRequestMessage ToSimpleHttpRequestMessage(this string text)
{
var lines = text.Split("\r\n");
var requestLine = lines[0].Split(' ');
var request = new HttpRequestMessage();
request.RequestUri = new Uri("http://" + lines[1].Split(": ")[1] + requestLine[1]);
request.Method = new HttpMethod(requestLine[0]);
if(lines.Length > 4)
{
request.Content = new StringContent(lines[4], Encoding.UTF8, lines[2].Split(": ")[1].Split("; ")[0]);
}
return request;
}
I need better if any one faced something like it.
I am doing a POC on sending data to Azure event hub using C#. The data will be posted over http unlike the Eventhub client. As per the requirements I cam creating a SAStoken to be embedded in http header. However when posting I get 501, Unauthorized access error. Not sure where I am going wrong. Here is the code that I have written
public static async Task<HttpResponseMessage> SendDataUsingHttp()
{
// Namespace info.
var serviceNamespace = "myeventhubs";
var hubName = "eventhub1";
var url = string.Format("{0}/publishers/{1}/messages", hubName, 1);
//var url = string.Format("{0}/messages", hubName);
var baseUri = new
Uri(string.Format("https://{0}.servicebus.windows.net/"
, serviceNamespace));
var SharedAccessKeyName = "All";
var SharedAccessKey = "<shared access key>";
var sasToken =
createSasToken(baseUri.ToString(),SharedAccessKeyName,
SharedAccessKey);
var evtData = new
{
Temperature = new Random().Next(20, 50)
};
var payload = JsonConvert.SerializeObject(evtData);
// Create client.
var httpClient = new HttpClient
{
BaseAddress = baseUri
};
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Authorization = new
System.Net.Http.Headers.AuthenticationHeaderValue
("SharedAccessSignature", sasToken);
var content = new StringContent(payload, Encoding.UTF8);
content.Headers.ContentType = new
System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
HttpResponseMessage result = null;
try
{
result = await httpClient.PostAsync(url, content);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return result;
}
private static string createSasToken(string baseUri, string keyName,
string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var week = 60 * 60 * 24 * 7;
var expiration = Convert.ToString((int)sinceEpoch.TotalSeconds +
week);
string stringToSign = HttpUtility.UrlEncode(baseUri) + "\n" +
expiration;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)); //--
var signature =
Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(
stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(baseUri), HttpUtility.UrlEncode(signature),
expiration, keyName);
return sasToken;
}
result
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1,
Content: System.Net.Http.StreamContent, Headers: {
Transfer-Encoding: chunked Strict- Transport-Security:
max-age=31536000 Date: Sun, 17 Jun 2018 08:35:43 GMT Server:
Microsoft-HTTPAPI/2.0 Content-Type: application/xml; charset=utf-8
}} Content: {System.Net.Http.StreamContent} Headers:
{Transfer-Encoding: chunked Strict-Transport-Security:
max-age=31536000 Date: Sun, 17 Jun 2018 08:35:43 GMT Server:
Microsoft-HTTPAPI/2.0
Based on your createSasToken method, it would generate the authorization header value with the following format:
Authorization: SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}
For your request, you also specify the following code:
System.Net.Http.Headers.AuthenticationHeaderValue("SharedAccessSignature", sasToken);
Using Fiddler to capture the network traces, you would find that your authorization header value in your sent request would look like this:
Authorization: SharedAccessSignature SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}
For your code, you need to adjust the format of your sasToken under the createSasToken method.
Moreover, the baseUri parameter of createSasToken method needs to be the full request path you are requesting. So you need to modify the related code under SendDataUsingHttp for generating the token as follows:
var sasToken =createSasToken(baseUri+url, SharedAccessKeyName, SharedAccessKey);
I'm new in using twitter API, I've successfully called:
https://api.twitter.com/1.1/statuses/user_timeline.json
api.twitter.com/1.1/followers/list.json
but when I call:
https://api.twitter.com/1.1/geo/search.json?query=Pakistan
I get Forbidden access.
Following is my request:
Method: GET, RequestUri: 'https://api.twitter.com/1.1/geo/search.json?query=Pakistan', Version: 1.1, Content: , Headers:
{
Authorization: Bearer xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzzzzzzzzzzz%aaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbb
}
And the response that I get is:
StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
strict-transport-security: max-age=631138519
x-connection-hash: 3a7f405036803861a700cef30f7b1e7f
x-response-time: 107
Date: Fri, 05 May 2017 03:18:15 GMT
Set-Cookie: guest_id=v1%3A149395429589966721; Domain=.twitter.com; Path=/; Expires=Sun, 05-May-2019 03:18:15 UTC
Server: tsa_o
Content-Length: 91
Content-Type: application/json; charset=utf-8
}
If you're interested in looking at my C# code that I'm using, here you go:
public async Task<IEnumerable<string>> GetTweetsByLatLong(double latitude, double longitude, int count, string accessToken = null)
{
if (accessToken == null)
{
accessToken = await GetAccessToken();
}
var requestUserTimeline = new HttpRequestMessage(HttpMethod.Get, string.Format("https://api.twitter.com/1.1/geo/search.json?query=Pakistan"));
requestUserTimeline.Headers.Add("Authorization", "Bearer " + accessToken);
var httpClient = new HttpClient();
HttpResponseMessage responseUserTimeLine = await httpClient.SendAsync(requestUserTimeline);
if (responseUserTimeLine.IsSuccessStatusCode)
{
var serializer = new JavaScriptSerializer();
dynamic json = ((serializer.Deserialize<object>(await responseUserTimeLine.Content.ReadAsStringAsync())) as Dictionary<string, object>).Values.ElementAt(0);
//new System.Collections.Generic.Mscorlib_DictionaryValueCollectionDebugView<string, object>((json as Dictionary<string, object>).Values).Items[0]
var enumerableTwitts = (json as IEnumerable<dynamic>);
if (enumerableTwitts == null)
{
return null;
}
return enumerableTwitts.Select(t => (string)(t["name"].ToString()));
}
else
{
return new string[] { responseUserTimeLine.ToString() };
}
}
public async Task<string> GetAccessToken()
{
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/oauth2/token ");
var customerInfo = Convert.ToBase64String(new UTF8Encoding().GetBytes(OAuthConsumerKey + ":" + OAuthConsumerSecret));
request.Headers.Add("Authorization", "Basic " + customerInfo);
request.Content = new StringContent("grant_type=client_credentials", Encoding.UTF8, "application/x-www-form-urlencoded");
HttpResponseMessage response = await httpClient.SendAsync(request);
string json = await response.Content.ReadAsStringAsync();
var serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(json);
return item["access_token"];
}
I believe it is because you are using Application-only authentication by providing a Bearer token.
See "Requires Authentication" in both
https://dev.twitter.com/rest/reference/get/geo/search
and
https://dev.twitter.com/rest/reference/get/statuses/user_timeline
And read https://dev.twitter.com/oauth
I got an issue with the HttpResponsemessage process, everything works for the sending request but during the readin of the responce i've got an error
InvalidOperationException : The character set provided in ContentType is invalid.
using (var handler = new HttpClientHandler())
{
if (handler.SupportsAutomaticDecompression)
{
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}
using (var client = new HttpClient(handler) { BaseAddress = new Uri(BaseAddress) })
{
Dictionary<string, string> dico = new Dictionary<string, string>();
dico.Add("username", _username);
dico.Add("password", _password);
HttpResponseMessage response = client.PostAsync("/auth", new FormUrlEncodedContent(dico)).Result;
var tokResult = response.Content.ReadAsStringAsync().Result;
var tokObj = JsonConvert.DeserializeObject<AuthResult>(tokResult);
string token = tokObj.Token;
return token;
}
}
header values of the response :
{StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:{ Connection: keep-alive Server: cloudflare-nginx Transfer-Encoding: chunked CF-RAY: 35e6bfcc8f3c3c77-CDG T411-node: webus1 Set-Cookie: __cfduid=db2de200ea64f72bef261054785e1047c1494690372; expires=Sun, 13-May-18 15:46:12 GMT; path=/; domain=.t411.al; HttpOnly Date: Sat, 13 May 2017 15:46:12 GMT X-Powered-By: PHP/5.5.38-4+deb.sury.org~xenial+1 Content-Type: text/html; charset=windows-1252}}
The solution I found is :
var request = (HttpWebRequest)WebRequest.Create(BaseAddress + "/auth");
var postData = "username=" + _username ;
postData += "&password=" + _password;
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (var stream = request.GetRequestStreamAsync().Result)
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponseAsync().Result;
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var tokObj = JsonConvert.DeserializeObject<AuthResult>(responseString);
string token = tokObj.Token;
return token;
So based on Tom Raz post Ionic push notification api in c# with WebApi. I tried to implement a method to send a push notification using the ionic push notifications api here is my code:
public void sendToIonic(string regId, string msg) {
using (var client = new HttpClient())
{
string data = "{ \"user_ids\":[\" "+ regId + "\"],\"notification\":{\"alert\":\" "+ msg + "\"}}";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(data);
client.BaseAddress = new Uri("https://push.ionic.io/api/v1/push");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("X-Ionic-Application-Id", "1d74b1f2");
var keyBase64 = "Basic %s" + "53a03dc7d9ce58511263e40580294f62af36b89be7cc4db2";
client.DefaultRequestHeaders.Add("Authorization", keyBase64);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://push.ionic.io/api/v1/push");
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
var response = client.SendAsync(request).Result;
}
}
But I keep getting the response error 403 Forbidden;. This is the complete response:
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Date: Fri, 15 Jan 2016 20:50:33 GMT
ETag: W/"35-nGlZv/eC8CyS+KJzQ1P9rg"
Server: Cowboy
Via: 1.1 vegur
X-Powered-By: Express
Content-Length: 53
Content-Type: application/json; charset=utf-8
}}
Not sure what is wrong. I am stuck. Any help would be appreciated.
var keyBase64 = "Basic %s" + "..."
%s this is to concatenate in python.
You need to convert to Base64
You can use
client.DefaultRequestHeaders.Add("X-Ionic-Application-Id", "1d74b1f2");
var IONIC_PRIVATE_KEY_BASE_64 = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("53a03dc7d9ce58511263e40580294f62af36b89be7cc4db2:")); // ends with two points
var keyBase64 = "Basic " + IONIC_PRIVATE_KEY_BASE_64 ;
client.DefaultRequestHeaders.Add("Authorization", keyBase64);
http://docs.ionic.io/docs/push-sending-push#section-authenticating-your-requests