How to get the header values in a GET request? - c#

System.Net.WebRequest req = System.Net.WebRequest.Create(URL);
req.Proxy = null;
System.Net.WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
string result = sr.ReadToEnd().Trim();
I have this code which makes a GET request on my URL and returns the JSON data. However, I also need to get the header values from it.
Example output of the URL is the following:
Content-Type: application/json
Content-Language: en
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Vary: Cookie, Accept-Language
Pragma: no-cache
Cache-Control: private, no-cache, no-store, must-revalidate
Set-Cookie: csrftoken=66161e4f97cbf771199ff78cfeea835e; expires=Sat, 20-Feb-2016 06:49:03 GMT; Max-Age=31449600; Path=/
Set-Cookie: mid=VOgqXwABAAHBumwiwEqLc2ScukeD; expires=Fri, 16-Feb-2035 06:49:03 GMT; Max-Age=630720000; Path=/
Connection: close
Content-Length: 108
{"status":"ok","shift":18,"header":"638wprvx7lg5Um0dZzBAKfjIkML12ChQ","edges":100,"iterations":10,"size":42}
Using my code, I can get the last JSON data returned, but I also need the headers. How can I do that? Thanks.

You can use Headers property of HttpRequest
Ref
resp.Headers
to get the headers for the response.

The HttpWebRequest has a built in property called Headers.
Please have a look at the MSDN page here:
https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.headers(v=vs.110).aspx
At the bottom of the page you'll find a very simpe code example that should get you started!

Related

Jira API Help C# HttpClient

Okay, so I'm very new to using API's in code and I've been able to use a few that were actually pretty easy. But none of them required authentication. I've been trying to use Jira's REST API service via C#'s HttpClient class. See code below:
public void UpdateJiraIssue(string issueValue)
{
string url = $#"http://jira.mySite.com/rest/api/2/issue/{issueValue}/editmeta";
string jsonString = #"myNeatJsonData";
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
//Initialize Client
HttpClient apiClient = new HttpClient();
apiClient.BaseAddress = new System.Uri(url);
apiClient.DefaultRequestHeaders.Accept.Clear();
byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
apiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
async Task RunJiraAPI()
{
using (HttpResponseMessage resp = await apiClient.PostAsync("editmeta", content))
{
if (resp.IsSuccessStatusCode)
{
var jsonSring = await resp.Content.ReadAsStringAsync();
}
}
}
RunJiraAPI();
return;
}
The problem I run into is that I get a 401 error (Authentication). Here's what my 'resp' object contains when I run the code:
resp: {StatusCode: 401, ReasonPhrase: ' ', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
X-AREQUESTID: 400x1314x1
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
X-ASEN: SEN-11158344
X-AUSERNAME: anonymous
Cache-Control: no-store, no-transform, no-cache
Set-Cookie: atlassian.xsrf.token=B2ZY-C2JQ-1AGH-PBLW_5ccc79da5af8e6abcb9bff5250f3305af3b2877a_lout; Path=/; Secure
WWW-Authenticate: OAuth realm="https%3A%2F%2Fjira.mySite.com"
X-Powered-By: ARR/3.0
X-Powered-By: ASP.NET
Date: Wed, 15 Jan 2020 13:40:22 GMT
Content-Length: 109
Content-Type: application/json; charset=UTF-8
}}
Request Message: {Method: POST, RequestUri: 'https://jira.rhlan.com/rest/api/2/issue/RHD-1116/editmeta', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Authorization: Basic cWE6aGVjc29mdDEyMw==
Accept: application/json
Content-Type: Application/json; charset=utf-8
Content-Length: 70
}}
Status Code: Unauthorized
I need to work on my json string a bit to get it working right (which is why I didn't include what it actually contains), but once I get passed the authentication error, I'll probably actually change things to do a get Jira issue via the API so I can see all the json data returned that way. Then I'll edit my json string accordingly.
Any ideas what I'm doing wrong here?
You can pass in credentials assuming you have a username and an api token.
string credentials= string.Format("{0}:{1}", username, apitoken);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(credentials);
And in your apiClient you can use it like this.
apiClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteCredentials));
You need a username and api-token. Your api-token should be your login password.

How to fix Bad Request when writing AppProperties for the file

There is a problem writing AppProperties for the file using the Google drive api. The request is executed, then an error is returned 400.
Request is sent via dotnet api:
public Resource ResourcePatch(string FileID, IDictionary<string, string> properties)
{
GoogleAPI.File file = new GoogleAPI.File() { AppProperties = properties };
var updateRequest = _driveService.Files.Update(file, FileId);
updateRequest.Fields = "id, appProperties";
file = updateRequest.Execute();
...
This is what is sent and what I get.
Request:
PATCH https://www.googleapis.com/drive/v3/files/1DUpjXjNro6LreMgyVbYW7k05eBes0A3o?fields=id%2C%20appProperties HTTP/1.1
User-Agent: Sberdisk google-api-dotnet-client/1.38.0.0 (gzip)
Authorization: Bearer ...
Content-Type: application/json; charset=utf-8
Host: www.googleapis.com
Content-Length: 49
Accept-Encoding: gzip, deflate
{"appProperties":{"SHARED_PROPERTY_NAME":"true"}}
Response, sometimes:
HTTP/1.0 200 This buggy server did not return headers
<html><title>Error 400 (Bad Request)!!1</title></html>
Sometimes:
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Thu, 07 Feb 2019 12:39:13 GMT
Vary: Origin
Vary: X-Origin
Content-Type: application/json; charset=UTF-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Alt-Svc: quic=":443"; ma=2592000; v="44,43,39"
Content-Length: 183
{
"id": "1nWtqhBYKSl0YhtLMypEx5rmAuo43-3Ts",
"appProperties": {
"SHARED_PROPERTY_NAME": "true"
}
}
Sometimes the request is executed, sometimes an Bad Request. I do't see system logic in this. What can be the reason?

Managing returncode from Newtonsoft.Json when not authorized

We have using an implementation login on a JWT portal.
When I post a valid user/pass, we have a token ok. But whe I post a invalid user/pass, the response has this format:
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
Cache-Control: no-cache
Set-Cookie: dnn_IsMobile=False; path=/; HttpOnly
Set-Cookie: .ASPXANONYMOUS=YrYcKYrviiUjmN7dSAd2DYWBO5W_Nj2yS_79eZ473OtallQXmOoE_6u73yOGOgBn0im8tE_dcUrIR74EYy_l8HKId7AvyY2OszmP1JrCkR6dLslS0; expires=Fri, 18-Nov-2016 06:11:07 GMT; path=/; HttpOnly
Set-Cookie: dnn_IsMobile=False; path=/; HttpOnly
Set-Cookie: .ASPXANONYMOUS=YrYcKYrviiUjmN7dSAd2DYWBO5W_Nj2yS_79eZ473OtallQXmOoE_6u73yOGOgBn0im8tE_dcUrIR74EYy_l8HKId7AvyY2OszmP1JrCkR6dLslS0; expires=Fri, 18-Nov-2016 06:11:07 GMT; path=/; HttpOnly
Set-Cookie: language=es-CO; path=/; HttpOnly
Set-Cookie: ARRAffinity=03cc22ac05b5cc76e788b382c1c33cccde1e727973fdb84dce1c542f8f1d9b46;Path=/;Domain=plcolabv2-pre.azurewebsites.net
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Bearer bad-credentials
Date: Fri, 09 Sep 2016 19:31:07 GMT
Content-Length: 0
Expires: -1
}}
Please, how can I get the results on first line, and store it on a variable? (StatusCode: 401, ReasonPhrase: 'Unauthorized'). When I post invalid user/pass, variable response have null value.
My code:
....
// Request body
byte[] byteData = Encoding.UTF8.GetBytes(jOneLogin);
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
response = await client.PostAsync(uri, content);
}
var results = JsonConvert.DeserializeObject<dynamic>(response.Content.ReadAsStringAsync().Result);
var crAccessToken = results.accessToken;
....
Maybe, is a simple question, answered in the past, but I can't find a specific post for that.
Thanks in advance.
As you are using HttpClient, you can just check HttpResponseMessage.IsSuccessStatusCode before calling JsonConvert.DeserializeObject(). See this answer for an example.

Why is HttpClient so much faster with HTTPS over HTTP?

I was investigating a strange bug the other day in which normalizing a URL would cause a massive 300% slowdown in my application:
if (!TryNormalize(uri, out uri))
throw new ArgumentException("URL is not a valid YouTube URL!");
string pageSource;
using (var http = new HttpClient())
pageSource = await http.GetStringAsync(uri);
When TryNormalize was commented out, GetStringAsync would take about .5s to complete. Yet when it was uncommented, downloading the string would take up to 2s. Turns out that TryNormalize was prefixing all the URLs it processed with "http://", and adding an extra S solved the problem.
So with that said, why does this happen? To my understanding, HTTPS should be slower because the string has to be encrypted before transmission from the server, while HTTP doesn't offer such an option. And even if I'm no expert on HTTP, 300% seems like quite a dramatic slowdown. Am I missing something here?
Edit: Source code of TryNormalize:
public static bool TryNormalize(string videoUri, out string normalized)
{
normalized = null;
var builder = new StringBuilder(videoUri);
videoUri = builder.Replace("youtu.be/", "youtube.com/watch?v=")
.Replace("youtube.com/embed/", "youtube.com/watch?v=")
.Replace("/v/", "/watch?v=")
.Replace("/watch#", "/watch?")
.ToString();
string value;
if (!Query.TryGetParamValue("v", videoUri, out value))
return false;
normalized = "http://youtube.com/watch?v=" + value; // replacing with HTTPS here results in 1.5s speedup
return true;
}
This is because there are many redirections when you use the variantions of youtube url. For example navigating to http://youtu.be/O3UBOOZw-FE results in two redirections.(see the Location header)
1.
HTTP/1.1 302 Found
Date: Fri, 21 Aug 2015 16:52:40 GMT
Server: gwiseguy/2.0
Location: http://www.youtube.com/watch?v=O3UBOOZw-FE&feature=youtu.be
Content-Length: 0
Content-Type: text/html
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
2.
HTTP/1.1 301 Moved Permanently
Date: Fri, 21 Aug 2015 16:52:40 GMT
Server: gwiseguy/2.0
Content-Type: text/html; charset=utf-8
X-Content-Type-Options: nosniff
Expires: Tue, 27 Apr 1971 19:44:06 EST
Content-Length: 0
Cache-Control: no-cache
X-XSS-Protection: 1; mode=block; report=https://www.google.com/appserve/security-bugs/log/youtube
Location: https://www.youtube.com/watch?v=O3UBOOZw-FE&feature=youtu.be
X-Frame-Options: SAMEORIGIN
until you finally get the url https://www.youtube.com/watch?v=O3UBOOZw-FE&feature=youtu.be
Since those redirections are handled automatically by HttpClient, you only see the final result of 3 requests.

Call PHP based webservice

I'm working on a asp.net webapplication, build in C#. I have to implement a third party web-service that is created using PHP. It is a very simple service containing only one function. I added the service reference using the wsdl, so far so good.
When I call the web-service function with the correct parameters it always returns null. I started troubleshooting with SoapUI. I captured the soap message from the application and pasted it in SoapUI, executed it and it returned the correct message. Using Fiddler I discovered something weird in the response from the web-service as shown in the raw output:
HTTP/1.1 200 OK
Date: Wed, 21 Nov 2012 15:24:31 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/0.9.8o
X-Powered-By: PHP/5.2.13-pl1-gentoo
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=ddc342cfe7e56e77456fe31b758bf3de; path=/
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 812
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/xml; charset=utf-8
?????????KS?0???`r?~?<??? ?I
I?????0??+?.????kK.????[E?????[???????}??g4
?1J???~w?i??<?M?+w??[>]ziIc???.?
???yvi?"x? F??d?Y?aR,4?X?
[UQ^F)?$`?
7??[?F"?$??h???S?a??4??Q?E??6Td,t6%Hg??w/)??????]??G* ?l[??&6?0?$??>??????~?????:??6??W#?a????E?G?
s??Z????§o?_??c??\???-???)?????cc??w???/??f??}?)??r???????T?/??? m??K??8? ?X?/F8?<???:?m???&f ?Z#[31?*?X,c?Z??0h"??aFb.?<??p??a???Q?B?r>????Z??5??6???????n\y?d?.??\??Hc]??
Z,?x??l???g?Q?*&???1?)??????^?????v??pQ???_y~??%??????*?
>???;??6?+?>???RQq?????a?(?Z????C?5???G??Ce??H?9??xYL|"??i?
e8?Vk???s???AK^?e~??
??(??Lt???r???vs????7??d?w???Jj-B????pt????c??MBi?s)Mo?.??^?aB3?x8&??:_K|???5???)[?M?Xc?j?zX?=G?i/??TO???g????5??c0??w???T??
The header is displayed correctly. The response is encoded and needs to be decoded. Both SoapUI and Fiddler are able to decode the response, but the proxy class can't and returns null.
How can I overcome this problem? Any help is greatly appreciated!
EDIT:
The way the service is called:
LisenceServiceFR.ServiceRegistration_PortTypeClient client = new LisenceServiceFR.ServiceRegistration_PortTypeClient();
LisenceServiceFR.aVehicleInfo info = client.getVehicleInfo("xxx", "xxx", licensePlate, "localhost");
Edit 2:
The response XML from Fiddler.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.audaconfr.com/ServiceRegistration.wsdl">
<SOAP-ENV:Body>
<SOAP-ENV:getVehicleInfoResponse>
<aVehicle>
<ns1:errorCode>200</ns1:errorCode>
<ns1:errorMessage>Success</ns1:errorMessage>
<ns1:vehicleXml>
<vehicule>
<carr>MONOSPACE COMPACT</carr>
<carr_cg>CI</carr_cg>
<co2>152</co2>
<!-- etc -->
</vehicule>
</ns1:vehicleXml>
</aVehicle>
</SOAP-ENV:getVehicleInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I ended up using HttpWebRequest to call the webservice:
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.InnerXml = xml;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(endPoint);
req.Timeout = 100000000;
if (proxy != null)
req.Proxy = new WebProxy(proxy, true);
req.Headers.Add("SOAPAction", "");
req.ContentType = "application/soap+xml;charset=\"utf-8\"";
req.Accept = "application/x-www-form-urlencoded";
req.Method = "POST";
Stream stm = req.GetRequestStream();
doc.Save(stm);
stm.Close();
WebResponse resp = req.GetResponse();
stm = resp.GetResponseStream();
StreamReader r = new StreamReader(stm);
string responseData = r.ReadToEnd();
XDocument response = XDocument.Parse(responseData);
/* extract data from response */
It was not the solution I was looking for, but is works like a charm.

Categories

Resources