HttpClient Time_wait - httpclient

I make connector from unity to influxdb using HttpClient. but this problum it was so angre, how can i do this code edit? I learned c# 3weeks ago.... i tryed
private static readonly HttpClient client = new HttpClient();
but many more new create tcp... time_wait
this is my code
code 1
public async Task GetPositionAsync()
{
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(Url))
{
using (HttpContent content = response.Content)
{
getdata = content.ReadAsStringAsync().Result;
}
}
}
client.Dispose();
}
code 2
HttpClient client = new HttpClient();
int refreshTime = 5;
client.DefaultRequestHeaders.Add("Authorization", "Token " + token);
//client.DefaultRequestHeaders.Add("Accept", "application/csv");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
var fluxQuery = "from(bucket: \"DT_Object\")\n"
+ "|> range(start: -6h)"
+ "|> filter(fn: (r) => r[\"_measurement\"] ==\" NPC\")"
+ "|> filter(fn: (r) => r[\"NAME\"] == \"NPC\")"
+ "|> filter(fn: (r) => r[\"_field\"] == \"X\" or r[\"_field\"] == \"Y\" or r[\"_field\"] == \"Z\")"
+ "|> aggregateWindow(every: " + refreshTime + "s, fn: mean, createEmpty: false)"
+ "|> yield(name: \"mean\")";
var data = new StringContent(fluxQuery, Encoding.UTF8, "application/vnd.flux");
var response = await client.PostAsync(requestUrl, data);
Debug.Log(response);
// var responseString = await client.GetStringAsync(requestUrl);
// Debug.Log("get data : " + responseString);
//response.Content = "application/CSV";
var result = response.Content.ReadAsByteArrayAsync();
Debug.Log("데이터 읽어줘 " + result.ToString());
if (result == null)
{
Debug.Log("결과없음");
}
Debug.Log("result : " + result);
client.Dispose();
}

The simplest solution is to reuse HttpClient:
private static readonly HttpClient client = new();
public async Task GetPositionAsync()
{
using (HttpResponseMessage response = await client.GetAsync(Url))
{
using (HttpContent content = response.Content)
{
getdata = await content.ReadAsStringAsync();
}
}
}

Related

Getting access token for SharePoint through http request via proxy server

I am able to get access token for SharePoint from accounts.accesscontrol.windows.net while I am running my application on a machine which is allowed to connect to external URL.
But when I am running my application on an environment where I can only go via a proxy server, its giving me 401: Permission denied (connect failed) even through I have added the proxy code. I am given a ProxyServer URL and port; its of type http.
Please find my code for direct hit below. This is working absolutely fine in open env:
private String getToken(String tenant_id,String client_id, String client_secret, String domain)
{
String resultToken=null;
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/"+ tenant_id+"/tokens/OAuth/2";
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
String jsonParam = "grant_type=client_credentials"
+ "&client_id="+client_id+"#"+tenant_id
+ "&client_secret="+client_secret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/" +domain+".com#"+tenant_id;
System.out.println("TokenRequestString : " + jsonParam);
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
// Extracting accessToken from string, here response
// (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}
Below is my code where I am trying to achieve the same thing through proxy server. This is throwing Permission Denied (401)
private String getToken(String tenant_id,String client_id, String client_secret, String domain)
{
String resultToken=null;
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/"+ tenant_id+"/tokens/OAuth/2";
URL url = new URL(wsURL);
// via Proxy
Proxy webProxy
= new Proxy(Proxy.Type.HTTP, new InetSocketAddress("internet.xyz.com", 83);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(webProxy);
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
String jsonParam = "grant_type=client_credentials"
+ "&client_id="+client_id+"#"+tenant_id
+ "&client_secret="+client_secret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/" +domain+".com#"+tenant_id;
System.out.println("TokenRequestString : " + jsonParam);
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
// Extracting accessToken from string, here response
// (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}

Xamarin Essentials Unable to exchange Okta authorization code for token

I was using OpenID and we have to switch to Xamarin.Essentials.WebAuthenticator.
I can get an authorization code from Okta using WebAuthenticator.AuthenticateAsync().
But, everything I try to then translate that code into an access token returns 400 Bad Request.
Okta's API error is "E0000021: HTTP media type not supported exception" and it goes on to say, "Bad request. Accept and/or Content-Type headers likely do not match supported values."
I have tried to follow https://developer.okta.com/blog/2020/07/31/xamarin-essentials-webauthenticator as much as possible, but we are not using the hybrid grant type like he is.
We are using only Authorization Code, which means I have to make a secondary call, and I have spent two days trying to figure out how.
private async Task LoginOktaAsync()
{
try
{
var loginUrl = new Uri(BuildAuthenticationUrl()); // that method is down below
var callbackUrl = new Uri("com.oktapreview.dev-999999:/callback"); // it's not really 999999
var authenticationResult = await Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(loginUrl, callbackUrl);
string authCode;
authenticationResult.Properties.TryGetValue("code",out authCode);
// Everything works fine up to this point. I get the authorization code.
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/token"
+"?grant_type=authorization_code"
+$"&code={authCode}&client_id={OktaConfiguration.ClientId}&code_verifier={codeVerifier}";
var request = new HttpRequestMessage(HttpMethod.Post, url);
var client = new HttpClient();
var response = await client.SendAsync(request); // this generates the 400 error.
}
catch(Exception e)
{
Debug.WriteLine($"Error: {e.Message}");
}
}
Here are the methods that produce the login url and a couple of other things:
public string BuildAuthenticationUrl()
{
var state = CreateCryptoGuid();
var nonce = CreateCryptoGuid();
CreateCodeChallenge();
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/authorize?response_type=code"
+ "&response_mode=fragment"
+ "&scope=openid%20profile%20email"
+ "&redirect_uri=com.oktapreview.dev-999999:/callback"
+$"&client_id={OktaConfiguration.ClientId}"
+$"&state={state}"
+$"&code_challenge={codeChallenge}"
+ "&code_challenge_method=S256"
+$"&nonce={nonce}";
return url;
}
private string CreateCryptoGuid()
{
using (var generator = RandomNumberGenerator.Create())
{
var bytes = new byte[16];
generator.GetBytes(bytes);
return new Guid(bytes).ToString("N");
}
}
private string CreateCodeChallenge()
{
codeChallenge = GenerateCodeToVerify();
codeVerifier = codeChallenge;
using (var sha256 = SHA256.Create())
{
var codeChallengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeChallenge));
return Convert.ToBase64String(codeChallengeBytes);
}
}
private string GenerateCodeToVerify()
{
var str = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
Random rnd = new Random();
for (var i = 0; i < 100; i++)
{
str += possible.Substring(rnd.Next(0,possible.Length-1),1);
}
return str;
}
'''
After much online research, I discovered the issue was with how I was doing my post to get the token. This is how I made it work:
public static Dictionary<string, string> JsonDecode(string encodedString)
{
var inputs = new Dictionary<string, string>();
var json = JValue.Parse(encodedString) as JObject;
foreach (KeyValuePair<string, JToken> kv in json)
{
if (kv.Value is JValue v)
{
if (v.Type != JTokenType.String)
inputs[kv.Key] = v.ToString();
else
inputs[kv.Key] = (string)v;
}
}
return inputs;
}
private async Task<string> ExchangeAuthCodeForToken(string authCode)
{
string accessToken = string.Empty;
List<KeyValuePair<string, string>> kvdata = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", authCode),
new KeyValuePair<string, string>("redirect_uri", OktaConfiguration.Callback),
new KeyValuePair<string, string>("client_id", OktaConfiguration.ClientId),
new KeyValuePair<string, string>("code_verifier", codeVerifier)
};
var content = new FormUrlEncodedContent(kvdata);
var request = new HttpRequestMessage(HttpMethod.Post, OktaConfiguration.TokenUrl)
{Content = content, Method = HttpMethod.Post};
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(request);
string text = await response.Content.ReadAsStringAsync();
Dictionary<string, string> data = JsonDecode(text);
data.TryGetValue("access_token", out accessToken);
return accessToken;
}

How to change throughput value of existing azure cosmosdb collection?

I want to reduce the throughput value of existing azure cosmos db collection using this rest API and it's giving a bad/unauthorized error. Kindly help me calling the API with proper input.
https://learn.microsoft.com/en-us/rest/api/cosmos-db/replace-an-offer
You need to provide authorization header
type={typeoftoken}&ver={tokenversion}&sig={hashsignature}
To start from replaceThroughput method
const replaceThroughput = async(req, res, next) => {
let collectionName = _.get(req, 'headers.collectionname');
let offerThroughput = _.get(req, 'headers.offerthroughput');
const container = await cosmosClient.database(process.env.COSMOS_DB_NAME).container(collectionName);
let containerResponse = await container.read().catch((error)=>{
let err = new Error();
err.statusCode = 404;
err.message = 'Collection not found';
next(err);
return;
});
let resourceId = _.get(containerResponse, 'body._rid', '');
console.log(resourceId)
let offerPayload = await getOfferPayload(resourceId);
_.set(offerPayload, 'content.offerThroughput', offerThroughput);
let offerResponse = await replaceOfferThroughput(offerPayload.id, offerPayload);
if (offerResponse.error) {
let err = new Error();
err.statusCode = 500;
err.message = 'Replace resource offer failed';
err.data = offerResponse.error;
next(err);
return;
} else {
res.end(JSON.stringify({'result': 'success', 'message': 'throughput updated', 'data': offerResponse}));
}
next();
};
const getOfferPayload = async (resourceId) => {
var dateString = new Date().toUTCString();
let authString = getAuthorizationTokenUsingMasterKey('GET','offers', '', dateString, process.env.COSMOS_DB_KEY);
const options = {
method: 'GET',
rejectUnauthorized: false,
uri: 'https://' + process.env.COSMOS_DB_NAME + '.documents.azure.com/offers',
headers: {
'x-ms-version': '2018-06-18',
'Authorization': authString,
'x-ms-date': dateString
}
};
try{
let response = await request(options);
response = JSON.parse(response);
response = _.filter(response.Offers, {offerResourceId: resourceId});
return response[0];
}catch(err){
return err;
}
};
const replaceOfferThroughput = async (offerResourceId, offerPayload) => {
var dateString = new Date().toUTCString();
let authString = getAuthorizationTokenUsingMasterKey('PUT','offers', offerResourceId, dateString, process.env.COSMOS_DB_KEY);
const options = {
method: 'PUT',
body: offerPayload,
json: true,
rejectUnauthorized: false,
uri: 'https://' + process.env.COSMOS_DB_NAME + '.documents.azure.com/offers/'+ offerResourceId,
headers: {
'x-ms-version': '2018-06-18',
'Authorization': authString,
'x-ms-date': dateString
}
};
try{
return await request(options);
}catch(err){
return err;
}
};
const getAuthorizationTokenUsingMasterKey = (verb, resourceType, resourceId, date, masterKey) => {
var key = Buffer.from(masterKey, "base64");
var text = (verb || "").toLowerCase() + "\n" +
(resourceType || "").toLowerCase() + "\n" +
(resourceId || "").toLowerCase() + "\n" +
date.toLowerCase() + "\n" +
"" + "\n";
var body = Buffer.from(text, "utf8");
var signature = crypto.createHmac("sha256", key).update(body).digest("base64");
var MasterToken = "master";
var TokenVersion = "1.0";
return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);
}
To Create Connection
const CosmosClient = require("#azure/cosmos").CosmosClient;
cosmosClient = new CosmosClient({
endpoint: process.env.COSMOS_DB_URL,
auth: {
masterKey: process.env.COSMOS_DB_KEY
}
});

Google API Batch Request - .NET REST Call Gives error

I am having .NET code to call the google api in batch request for getting the message details for multiple Ids. The request I am creating, when run through postman it works perfectly but when run this console app it gives me the Response Status code = 0 and Error Specified value has invalid CRLF characters.\r\nParameter name: value
Can someone please look into this and help me ... I have searched almost everything now but could not get any solution.
Here is my code --
var baseUrl = "/gmail/v1/users/" + _accountID + "/messages/";
RestClient client = null;
RestRequest request = null;
StringBuilder sbBody = null;
for (int j = 0; j < _messageId.Count; j++)
{
msgCount++;
if (msgCount == 1)
{
boundary = "testing_batch";
sbBody = new StringBuilder();
client = new RestClient("https://www.googleapis.com/batch/");
request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "multipart/mixed; boundary=\"" + boundary + "\"");
request.AddHeader("Authorization", "Bearer " + accessToken);
}
sbBody.Append(string.Format("--{0}\n", boundary));
sbBody.Append("Content-Type: application/http\n\n");
sbBody.Append(string.Format("GET {0}{1}\n\n", baseUrl, _messageId[j]));
if (msgCount == 1)
sbBody.Append(string.Format("--{0}--", boundary));
if (msgCount == 1)
{
msgCount = 0;
//request.AddBody(sbBody.ToString());
request.AddHeader("RequestBody", sbBody.ToString());
IRestResponse response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
//Do nothing for now
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
Console.ReadLine();
break;
}
else
{
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
Console.ReadLine();
break;
}
}

Async POST fails on WP7 and F#

When I do let! read = from.AsyncRead buf in F#, it blocks and doesn't return until the TCP socket is dead. Why? And how do I fix it?
Its code:
module StreamUtil
open System.IO
/// copy from 'from' stream to 'toStream'
let (|>>) (from : Stream) (toStream : Stream) =
let buf = Array.zeroCreate<byte> 1024
let rec doBlock () =
async {
let! read = from.AsyncRead buf
if read <= 0 then
toStream.Flush()
return ()
else
do! toStream.AsyncWrite(buf, 0, read)
return! doBlock () }
doBlock ()
It's being called from this code:
use fs = new FileStream(targPath, FileMode.CreateNew, FileAccess.ReadWrite)
do! req.InputStream |>> fs
and requested over HTTP with this code from Windows Phone 7.1 emulator:
public void Send()
{
var b = new UriBuilder(_imageService.BaseUrl) {Path = "/images"};
var req = WebRequest.CreateHttp(b.Uri);
req.ContentType = "image/jpeg";
req.Method = "POST";
var imgLen = SelectedImage.ImageStream.Length;
req.Headers[HttpRequestHeader.ContentLength] = imgLen.ToString(CultureInfo.InvariantCulture);
req.Accept = "application/json";
req.BeginGetRequestStream(RequestReady, new ReqState(req, imgLen));
}
void RequestReady(IAsyncResult ar)
{
var state = (ReqState)ar.AsyncState;
var req = state.Request;
var reqStream = req.EndGetRequestStream(ar);
SmartDispatcher.BeginInvoke(() =>
{
using (var sw = new StreamWriter(reqStream))
using (var br = new BinaryReader(SelectedVoucher.ImageStream))
{
var readBytes = br.ReadBytes(state.ImgLen);
// tried both 2
sw.Write(readBytes);
//sw.Write(Convert.ToBase64String(readBytes));
sw.Flush();
sw.Close();
}
req.BeginGetResponse(ResponseReady, req);
});
}
// WHY IS IT YOU ARE NOT CALLED???
void ResponseReady(IAsyncResult ar)
{
try
{
var request = (HttpWebRequest)ar.AsyncState;
var response = request.EndGetResponse(ar);
SmartDispatcher.BeginInvoke(() =>
{
var rdr = new StreamReader(response.GetResponseStream());
var msg = rdr.ReadToEnd();
var imageLocation = response.Headers["Location"];
Debug.WriteLine(msg);
Debug.WriteLine(imageLocation);
});
}
catch (WebException ex)
{
Debug.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
Unsuccessfully. The ResponseReady callback is never reached.
Meanwhile, this code works excellent:
open System
open System.Net.Http // WebAPI nuget
let sync aw = Async.RunSynchronously aw
let postC<'a> (c : HttpClient) (r : Uri) (cont : HttpContent) =
let response = sync <| Async.AwaitTask( c.PostAsync(r, cont) )
let struc:'a = sync <| deserialize<'a> response
response, struc
let withContent<'a> (fVerb : (HttpClient -> Uri -> HttpContent -> _ * 'a))=
let c = new HttpClient()
fVerb c
[<Test>]
let ``POST /images 201 + Location header`` () =
let post = withContent<MyImage> postC
let bytes = IO.File.ReadAllBytes("sample.jpg")
let hash = SHA1.Create().ComputeHash(bytes) |> Convert.ToBase64String
let pic = new ByteArrayContent(bytes)
pic.Headers.Add("Content-Type", "image/jpeg")
pic.Headers.Add("X-SHA1-Hash", hash)
let resp, ri = (resource "/images", pic) ||> post
resp.StatusCode =? Code.Created
ri.sha1 =? hash
mustHaveHeaders resp
I couldn't get Fiddler2 working with WP7.
EDIT: Welcome to a yak. I've moved onto greener pastures myself ;)
YOu should put the bytes into the before sending and using BufferStream INput output