C# socket download file from REST API - c#

I'm talking to a custom API, that will give me a file, if I send a GET request, with a body. And yes, I'm fully aware of how horrible that is, so please don't remind me.
I'm using Sockets to send the requests, and normally these GET requests return JSON data, which I can read just fine. However, I now need to download a file, and the socket keeps on closing. To be specific, I keep on getting this exception:
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
If I use curl to make the request, I get the file:
curl -d '{"thing" : "blah"}' -H "Content-Type: application/json" -X GET http://127.0.0.1:1337/api/0.1/test/download > test.zip
If I use fiddler, I get the file returned.
But C# sockets keep on throwing that exception. I don't have any code to show, as I really don't know the best way to handle the data transfer. But I've tried no end of loops, and nothing seems to be working. If anyone could provide some guidance on how to do this, I'd appreciate it.
Thanks

Related

How to consume a socket.io WebSocket API in C#

I need to consume a third-party WebSocket API in .NET Core and C#; the WebSocket server is implemented using socket.io (using protocol version 0.9), and I am having a hard time understanding how socket.io works... besides that the API requires SSL.
I found out that the HTTP handshake must be initiated via a certain path, which is...
socket.io/1/?t=...
...whereby the value of the parameter t is a Unix-timestamp (in seconds). The service replies with a session-key, timeout information, and a list of supported transport protocols. Due to simplicity, this first request is made via HttpClient and does not involve any additional headers.
Next, another HTTP request is required, which should result in an HTTP 101 Switching Protocol response. I specified the following headers in accordance to the previous request...
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: ...
Sec-WebSocket-Version: 13
...whereby the value of the Key-header is a Base64-encoded GUID-value that the server will use to calculate the Sec-WebSocket-Accept header value. I also precalculate the expected Sec-WebSocket-Accept header value, for validation...
I tried to make that request using HttpClient as well, but that does not seem to work... I actually don´t understand why, because I expect an HTTP response. I also tried to make the request using TcpClient by sending a manually prepared GET request over a SslStream, which accepts the remote certificate as expected. Sending data seems to work, but there´s no response data... the Read-method returns zero.
What do I miss here? Do I need to setup a listener for the WebSocket connection as well, and if yes how? I don´t want to implement a feature complete socket.io client, I´d just like to keep it as simple as possible to catch some events...
The best way of debugging these issues is to use a sniffer like wireshark or fiddler. Often connect using an IE and compare IE results with my application and modify my app so it works like the IE. Using WebClient instead of HttpClient will also work better because the WebClient does more automatically than the HttpClient.
A web connection uses the header of the client and the headers in the server webpage to negotiate a connection mode. Adding additional headers to you client will change the connection mode. Cookies are also used to select the connection mode. Cookies are the results of previous connection to the same server which shortens the negotiations and stores info from previous connection so less data has to be downloaded from server. The server remembers the cookies. Cookies have a timeout and is kept until timeout expires. The IE history in your client has a list of IP addresses and Net automatically sends the cookies associated with the server IP.
If a bad connection is made to the server the cookies is also bad so the only was of connection is to remove the cookie. Usually I go into the IE and delete cookies manually in the IE history.
To check if a response is good the server returns a status. A completed response contains a status 200 DONE. You can get status which are errors. You can also get a 100 Continue which means you need to send another request to get the rest of the webpage.
Http has 1.0 (stream mode) and 1.1 (chunk mode). Net library doesn't work with chunk. Chunk requires client to send message to get next chunk and I have not found a way in Net to send the next chunk message. So if a server responds with a 1.1 then you have to add to your client headers to use 1.0 only.
Http uses TCP as the transport layer. So in a sniffer you will see TCP and HTTP. Usually you can filter sniffer just to return Http and look at header for debugging. Occasionally TCP disconnects and then you have to look at TCP to find why the disconnect occurs.

Accessing OneDrive from Desktop App

I'm trying to get to grips with OneDrive, using this tutorial:
https://msdn.microsoft.com/en-us/library/hh826529.aspx
When I run in code, it gets as far as the makeAccessTokenRequest function, sending the following requestURL:
"https: //login.live.com/oauth20_token.srf?client_id=[myclientID] &client_secret=[myclientsecret]&redirect_uri=https:// login.live.com/oauth20_desktop.srf&grant_type=authorization_code&code=[authcode]"
(please ignore the spaces after "https:", I had to add them here to allow the question)
[myclientid], [myclientsecret], and [authcode] all appear to be populated correctly. It seems to get a response, as it runs the function "accessToken_DownloadStringCompleted", but throws a "TargetInvocationException" error, The inner message of the error is ""The remote server returned an error: (400) Bad Request.".
Could anyone throw any light on this? I'm completely new to this, so apologies if my question makes no sense, or is irritatingly vague..
Requests to the oauth20_token.srf end point need to be a POST with the parameters in the body of the post, instead of the query string. Since you didn't mention what code you're using to build the HTTP request it's hard to provide an example, but take a look at RedeemAuthorizationCodeAsync in my sample OAuth 2 project for an idea.
The outgoing request should look like this:
POST https://login.live.com/oauth20_token.srf
Content-Type: application/x-www-form-urlencoded
client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}&code={code}&grant_type=authorization_code
You may also find this tutorial easier to follow than the one you linked with: https://dev.onedrive.com/auth/msa_oauth.htm.
If you are doing something with OneDrive (you tagged the post OneDrive) then you may want to consider using the OneDrive SDK instead. It includes authentication for several types of .NET projects so you don't need to figure out how to do auth yourself.

How cURL POST image file works?

I am trying to use the new Facebook Messenger Platform API to send image message using image file from application directory.
Facebook gives the example using cURL like below:
curl \
-F recipient='{"id":"USER_ID"}' \
-F message='{"attachment":{"type":"image", "payload":{}}}' \
-F filedata=#/tmp/testpng.png \
"https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN"
But I am trying to use the API with C#. For your information, I have successfully use the API if I use the file from an internet url.
I have tried to fill in the filedata property by using base64 string of the image file, but unsuccessful.
Kindly explain how does cURL works with the given file path especially image and create a POST request to the web server? And if possible, what options do I have to do it with C#?
The -F option is for form. This is equivalent to issuing a POST request with the Content-Type header of multipart/formdata and the request body containing all the key-value pairs listed with a proper boundary set. cURL will read the binary data and put the bytes in the correct boundary in the request. There are many examples online for C# to submit a multipart/formdata request. Look into HttpClient or WebClient file uploads and you'll find what you need.
I'll be away from a computer for a few days and submitting sample code from a mobile device isn't the easiest thing to do. If you need some sample code, let me know.

Icecast 2: protocol description, streaming to it using C#

I need to write an Icecast 2 client that will be able to stream audio from the computer (mp3-files, soundcard recording and so forth) to the server. I decided to write such a client on C#.
Two questions:
1) It will be very useful to know common guidelines (best practices, maybe tricks) I may/should/must use to seamlessly work with streamed audio (streamed over network, of course) in C#. Some general technical documentation about streaming over TCP/IP in common and ICY in particular, advices and notes on the overall architecture of the application will be very appreciated.
2) Is there any good documentation regarding the Icecast 2 streaming protocol? I couldn't find those docs on the official site of Icecast. I don't want to extract the protocol description directly from the source code of it. If the protocol is really simple and neat, could anybody provide a summary of it right here?
As far as I know, there is no protocol spec anywhere, outside of the Icecast source code. Here's what I've found from packet sniffing:
Audio Stream
The protocol is similar to HTTP. The source client will connect to the server make a request with the mountpoint, and pass some headers with information about the stream:
SOURCE /mp3test ICE/1.0
content-type: audio/mpeg
Authorization: Basic c291cmNlOmhhY2ttZQ==
ice-name: This is my server name
ice-url: http://www.google.com
ice-genre: Rock
ice-bitrate: 128
ice-private: 0
ice-public: 1
ice-description: This is my server description
ice-audio-info: ice-samplerate=44100;ice-bitrate=128;ice-channels=2
If all is good, the server responds with:
HTTP/1.0 200 OK
The source client then proceeds to send the binary stream data. Note that it seems some encoders don't even wait for the server to respond with 200 OK before they start sending stream data. Just headers, an empty line, and then stream data.
Meta Data
Meta data is sent using an out-of-band HTTP request. The source client sends:
GET /admin/metadata?pass=hackme&mode=updinfo&mount=/mp3test&song=Even%20more%20meta%21%21 HTTP/1.0
Authorization: Basic c291cmNlOmhhY2ttZQ==
User-Agent: (Mozilla Compatible)
The server responds with:
HTTP/1.0 200 OK
Content-Type: text/xml
Content-Length: 113
<?xml version="1.0"?>
<iceresponse><message>Metadata update successful</message><return>1</return></iceresponse>
Also note that both the audio stream and meta data requests are sent on the same port. Unlike SHOUTcast, this is the base port that the server is running on.
I'm going to comment here despite this question being quite old.
Icecast is HTTP compliant. This was always the case for the listener side (plain and simple HTTP1.0, RFC 1945), starting with 2.4.0 it's also true for the source client side.
To implement a source client it's a PUT request in compliance with HTTP 1.1 aka RFC2616. Some options can be set through HTTP headers, for details please refer to the current Icecast documentation.
If you send one of the supported container formats: Ogg or WebM (technically EBML), then this is all you need to know. To make it clear this covers at leastOpus, Vorbis, Theora and VP8 codecs.
Please note that while generally working fine, other formats are technically not supported. Icecast only passes through the stream without any processing in such a case.
If you need help or have further questions, then the official mailing lists and the IRC channel are the right place to go.
Looked at Icecast2 a good long while ago: best reference I could find was at http://forums.radiotoolbox.com/viewtopic.php?t=74 link (I should print that out, took me forever to figure out the proper Google spell to cast to surface that again). It appears to cover source to server and server to client.
Questions remain about just how accurate it is: I got about halfway through an Android implementation before other things consumed me, and I can't quite remember what was wrong with the communication between my implementation of that and VLC/Winamp, but honestly it was the closest thing I could find to a spec.
The best description I know is here: https://gist.github.com/ePirat/adc3b8ba00d85b7e3870
#ePirat is xpiph/icecast core committer.

400: BadRequest with .Net Mass Downloader 1.5.0.1

Has anybody else had trouble with getting the .Net Framework source code? Google doesn't have anything to say about this error message, and neither does the CodePlex issue tracker.
Here is the command I'm using to get the source code for the modules that make up mscorlib.dll. Am I doing something obviously wrong?
NetMassDownloader.exe -o source -f "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll"
The 400 Bad Request error is an HTTP status code that means that the request you sent to the website server was somehow malformed therefore the server was unable to understand or process the request.
Resolution
Check for errors in the URL. The most common reason for a 400 Bad Request error is because the URL was typed wrong or the link that was clicked on points to a URL with some kind of mistake in it.
Though it's rare, the 400 Bad Request error could be an issue with the web site's server that you are trying to access.
Download it in another computer and copy/paste that folder to your own computer. I've got a similar problem with the tool, and that was my workaround.

Categories