Add header to response of socket in C# - c#

I'm trying to exchange data between a web page and a c# socket.
The c# socket is running on the localhost.
The webpage runs on a server and points to the localhost.
When the webpage sends a Get request to the c# socket an cross-domain error is shown.
XMLHttpRequest cannot load http://localhost:12345/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.1.3:9000' is therefore not allowed access.
This is the JS running on the web page (Angular).
var serviceUrl = 'http://localhost:12345';
var service = $resource(
serviceUrl,{}, {
getCard: {
method: "GET"
}
}
);
service.getCard();
This is a part of the code from the c# console application.
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend( byteData
, 0
, byteData.Length
, 0
, new AsyncCallback(SendCallback)
, handler
);
How can i add header information to the response.
The headers must be: Access-Control-Allow-Origin: *
It doesnt work when i add it in front of the string.

The header has to be added when you serve the page, not from the socket response. It's just a plain old HTTP header.
If you use IIS to serve your web page, do something like this before sending the page:
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

Related

gRPC Client Never Receives Response Headers

I want to send information about the current client version from the server in all responses to the callers.
I want to have this information in the HTTP header. But I am not able to read the headers in the client.
I call the method WriteResponseHeaderAsync in the server method or interceptor (tried both). I see (Fiddler) that the header is in the response header.
But, I cannot read this header on the client or in the interceptor on the client. I tried everything.
My code in method:
var result = AuthorizationClient.LoginAsync(loginRequest);
var responseHeaders = await result.ResponseHeadersAsync;
ResponseHeaders is empty (responseHeaders.Count is 0) all time. I am able to use Trailers but the right place is HTTP header.
Is possible to read the response headers? Is possible to read the response headers in interceptors?
If yes, how?
I am using: C#, Grpc.AspNetCore.Web 2.51.0 (on server), Grpc.Net.Client.Web 2.51.0 (Client. Blazor WebAssembly)

HttpListener ignoring everything after # (hash) in request

So I'm new to C# and I don't know if what I'm seeing is obvious and intended behavior or if there's some nuance to the objects I'm using.
I'm trying to set up a server to handle a redirect for an oauth flow for a StackOverflow app. The redirected url constructed looks like localhost:8080/#access_token=12345.
I basically have the following set up as my simple server to handle the redirect request and save the access_token.
public class ImplicitFlowHttpServer
{
public int Port = 8080;
private HttpListener _listener;
public void Start()
{
var prefix = $"http://*:8080/";
_listener = new HttpListener();
_listener.Prefixes.Add(prefix);
_listener.Start();
_listener.BeginGetContext(new AsyncCallback(ListenerCallback), _listener);
}
private async void ListenerCallback(IAsyncResult result)
{
if (_listener.IsListening)
{
string oauthCode;
var context = _listener.EndGetContext(result);
var request = context.Request;
// code to send response, not relevant to my question
HttpListenerResponse response = context.Response;
byte[] page = Encoding.ASCII.GetBytes(
"You can close this browser tab now.");
response.ContentLength64 = page.Length;
Stream output = response.OutputStream;
output.Write(page, 0, page.Length);
output.Close();
//
Console.WriteLine($"Should receive a request to localhost:8080/#access_token=<token>");
Console.WriteLine($"How can I see the access_token?");
Console.WriteLine($"request.Url: {request.Url}");
Console.WriteLine($"request.Url.Fragment: {request.Url.Fragment}");
Console.WriteLine($"request.RawUrl: {request.RawUrl}");
Console.WriteLine($"request.Url.AbsoluteUri: {request.Url.AbsoluteUri}");
Console.WriteLine($"request.Url.OriginalString: {request.Url.OriginalString}");
// <here is code to parse the access_token if it existed>
// <here is code to stop the server>
}
}
}
You can see I'm expecting the hash somewhere in that request object, that the #access_token would exist and I just have to figure out how to get it out, but I think it's just cleaned out altogether.
It doesn't have to do with the redirect, as I have the same problem if I spin up the server and then do curl "localhost:8080/?q=123&hello=world\#access_token=123456"
With the above code I'll see
request.Url: http://localhost:8080/?q=123&hello=world%5C
request.Url.Fragment:
request.RawUrl: /?q=123&hello=world\
request.Url.AbsoluteUri: http://localhost:8080/?q=123&hello=world%5C
request.Url.OriginalString: http://localhost:8080/?q=123&hello=world%5C
So given that I'm stuck with this access token "in the hash", how am I supposed to get the access_token from that redirect?
Fragment part of url (thing after the #) is special in that it's only for client-side use. The agent (web browser, curl etc) will remove fragment part from url when sending request to server. So it works as expected.
This is also the reason why token is passed this way in this oauth flow - so that when redirect happens, the token is not accessible to server, only to client.
As for how to solve this in your case, note how documentation at your link states:
The explicit flow should be used by server-side applications, with
special care taken to never leak client_secret. Client side
applications should use the implicit flow.
You are using implicit flow. If you would use explicit flow then token would be accessible to your server.

React - Can't fetch image from URL but works in C#

I've a problem which I find a bit weird but it is surely obvious for you guys. I'm trying to fetch an image as blob and then convert it to base64 to store it in Azure storage later on. I get the URL for the image from an object and want to download it as base64 to my react app. I'm able to get the image and put it into a html image tag as source , and it works just fine, the image shows up. On my server I can get the image via a HTTP client request and get it just fine too.
In C#:
using (var client = new HttpClient())
using (HttpResponseMessage response2 =
await client.GetAsync("URL HERE"))
{
byte[] fileContents = await response2.Content.ReadAsByteArrayAsync()>
}
When I'm trying to fetch the image in my react app like this:
const response = await fetch('URL HERE');
OR
const response = await fetch('URL HERE', {
method: 'GET',
mode: 'no-cors',
headers: {},
});
OR
let file = await fetch('URL HERE',
{
method: 'GET',
mode: 'no-cors',
})
.then((r) => r.blob())
.then((blobFile) => {
return new File([blobFile], 'FileName', { type: 'image/png' });
});
Why is this happening in React but in C# everyting works fine and how to solve it? It eaither shows as CORS-error OR the blob is empty, size 0. If I click the link I reach the image so the URL is fine too.
Any suggestions?
Many thanks!
no-cors option is rarely a good way to fix cors errors. When you use React you use browser's system and browser send you a cors errors when it not receive a correct response. For example, if your server sends you a 500 error, oftenly you will not receive the 500 error but a cors error.
Did you try to make the same request from React with Postman ? I think, if it works woth C#, it will probaly works with Postman but just to try.
Did you make some console logs like this :
let file = await fetch('url')
.then(r => {
console.log(r);
return r.blob();
)
.then((blobResponse) => {
console.log(blobResponse);
return blobResponse; // if you want to dl the file make a new File is probably not necessary : URL.createObjectURL(blob)
});
Maybe it is a real CORS error and so you should check your server and API configuration. There is a lot of issues about it on internet.
If it is, try something like this on your API response : (do not keep 'Access-Control-Allow-Origin', '*' on production)
$response->headers->set('Access-Control-Expose-Headers', 'Access-Control-*');
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Headers', '*');
$response->headers->set('Access-Control-Allow-Methods', 'HEAD, PUT, GET, POST, DELETE, OPTIONS');
$response->headers->set('Allow', 'HEAD, PUT, GET, POST, DELETE, OPTIONS');
Maybe you need too, to make a response for the OPTIONS http request. Browser send it before your request to ensure that your request will be received :
if ($request->getMethod() == 'OPTIONS') {
return $this->jsonResponse([]);
}

How can i read client request?

I have create an httplistener. So i need when client will send me data to read them. The problem is that i dont know how client should send the data
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://192.168.1.26:8282/");
listener.Prefixes.Add("http://localhost:8282/");
listener.Prefixes.Add("http://127.0.0.1:8282/");
listener.Start();
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
for (;;)
{
Console.WriteLine("Listening...");
// Note: The GetContext method blocks while waiting for a request.
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
string text;
using (var reader = new StreamReader(request.InputStream,
request.ContentEncoding))
{
text = reader.ReadToEnd();
MessageBox.Show(text);
}
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "HelloWorld";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}).Start();
}
So from client i send this command:
GET / 192.168.1.26:8282 HTTP/1.0
But i'm getting this message
Recv 34 bytes
SEND OK
+IPD,1,518:HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Wed, 13 Jun 2018 13:16:03 GMT
Connection: close
Content-Length: 339
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Header</h2>
<hr><p>HTTP Error 400. The request has an invalid header name.</p>
</BODY></HTML>
1,CLOSED
I cant understand what is wrong. Also in my code i set to get a message box every time a request will happen. But it never runs
This s what mozilla is sending
You are not attempting to invoke the service correctly. Here is your client request:
GET / 192.168.1.26:8282 HTTP/1.0
What you should be doing is first establishing a socket connection to host 192.168.1.26 over port 8282. Then you must issue a HTTP request in a valid format:
GET / HTTP/1.0
Don't forget to add some newlines after the request (ie: \r\n\r\n). Then your web server should respond to the HTTP request.
Quick example in Telnet:
telnet 192.168.1.26 8282
GET / HTTP/1.0
Quick example with netcat:
nc 192.168.1.26 8282
GET / HTTP/1.0
Note that these quick examples are provided just to help you ensure that your web service is accessible and functioning correctly. Ideally, you would likely use a more robust HTTP client that is customized for whatever your particular needs are. The process is still the same:
Establish a connection to your host IP address over the listening port
Issue a HTTP request in a valid format: (HTTP_VERB PATH HTTP_VERSION)
*) Maybe check out the developer tools in your browser of choice (F12 -> Network) to see how HTTP headers are sent as well.
Parse the response in some meaningful way.
"Also in my code i set to get a message box every time a request will happen." - You should try putting in a manual message to the message box, instead of reading from the input stream. This is a good debugging technique. In a HTTP GET request you generally are not sending data except in the form of optional query string parameters. I have a feeling that you are not getting the results you are expecting because you are reading from input that isn't there. Before reading from the stream input, first make sure that the connection is successful.

Communicate to Apache Server

Does any one know, how to communicate to Apache server from client side using Win32 or C#.
and can i get the control to execute the process at server? if so how to do?.
how to receive file sent by apache?.
Please help me...
Thanks
You can use HTTPWebRequest and HTTPWebResponse to make a request to a web server and receive a response.
For example
static void Main(string[] args)
{
// used to build entire input
StringBuilder sb = new StringBuilder();
// used on each read operation
byte[] buf = new byte[8192];
// prepare the web page we will be asking for
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create("http://www.mayosoftware.com");
// execute the request
HttpWebResponse response = (HttpWebResponse)
request.GetResponse();
// we will read data via the response stream
Stream resStream = response.GetResponseStream();
string tempString = null;
int count = 0;
do
{
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text.
// Not needed if you'll get binary content.
tempString = Encoding.ASCII.GetString(buf, 0, count);
// continue building the string
sb.Append(tempString);
}
}
while (count > 0); // any more data to read?
// print out page source
Console.WriteLine(sb.ToString());
}
Okay. Assuming you are talking about "Apache httpd", then we are talking about a server which talks HTTP. Pretty much any programming language has some "HTTP Client" classes. In the case of C#, you can use HttpWebRequest. Vinko gave a great "copy/paste" example.
To run a process on the server-side, you need some "server side scripting". If there is no module available for the httpd server, then you can always resort to CGI. This is potentially dangerous, if not careful though. But you can say this about all server-side scripting (the "if not careful" is important here).
As it sounds like, you are new to dynamic web development. And, as much as I dislike it, I have to say that the PHP community is a great starting point.
To give a rough overview of how things work:
The client (You C# app) make a "request" to the server (by default a TCP connection to port 80)
As the server (httpd) is listening on this port, it accepts this connection and starts "talking HTTP"
The server retrieves the URL from the HTTP GET command and decides what to do with it.
If this URL maps to a static resource, the server sends a "response" with the resource's content and is done.
If this URL maps to a dynamic resource, the server delegates the work to another process. This process executes, and the http-server receives the standard output of the process as result (In the case of PHP, CGI, and other similar technologies). The server then sends this result back to the client.
What I understood the least when I got started were the "cryptic" httpd-configurations. They are simple to understand though. They are there to tell the server how (and what) to map to the external process (as noted in step 4a and 4b).
So, in the case of PHP:
LoadModule php5_module modules/libphp5.so
This makes the "external process" and configuarion directives available to the server (loads the extensions).
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
The default Apache-httpd handler assumes that a URL maps to a File on the file system. This configuration directive tells httpd to process (handle) each filename ending with ".php" using the PHP module before returning it to the client.
Final note
These steps are very similar for other server-side applications. I only gave PHP as a practical example. And it's got very good documentation.

Categories

Resources