Z
Z
Zakharov Alexander2016-07-12 09:11:38
Programming
Zakharov Alexander, 2016-07-12 09:11:38

C#, need to send a raw HTTP(S) request?

Hello.
It is required in C# to send a raw HTTP (S) request in the form as "mother gave birth":

GET http://HOST:9200/_search HTTP/1.1
Host: HOST:9200

{
    "from" : 0,
    "size" : 10,
    "query" : {
        "indices" : {
            "indices" : ["контрагенты"],
            "query" :{"match_all":{}},
            "no_match_query" : "none"
        }
    },
    "filter" : {
        "and" : [
            {"or" : [{
                    "type" : { "value" : "v" }
            }]},
            {"or" : [{
                "terms":{"ID":["1190"]}
            }]}
        ]
    },
    "highlight" : {
        "fields" : {
            "*" : {}

        }
    }
}

No hostname parsing in code, etc. Like in fiddler-composer?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
P
Peter, 2016-07-12
@AlexZaharow

This is how you make a normal TCP / IP connection, i.e. open a socket on the port 9200 you need and send all this data.
Here is an example of such a connection

R
Rou1997, 2016-07-12
@Rou1997

What you have in question is an HTTP packet, open a TCP/IP connection and send, just don't forget the new line (\n).

Z
Zakharov Alexander, 2016-07-12
@AlexZaharow

Got it!
A small subtlety - the server is ElasticSearch.
Indeed, the decision through the
right one. But! You need to be VERY careful about what is written in the headings, and especially the heading " Content-Length: NNN ":
1. Be sure to insert it, even if it is not specified!
2. Correctly count the length of the request body. Not by characters, but by bytes.
Here's a revised MS code example from Piotr 's advice , which already works fine:

private void btnRequest_Click(object _sender, EventArgs e)
        {
            /* Текстовое поле, из которого я беру текст вида:
GET http://HOST:9200/_search HTTP/1.1
Host: HOST:9200

{
....
    "highlight" : {
        "fields" : {
            "*" : {}

        }
    }
}
           */
            string str = request_text.Text; 
            byte[] bytes = new byte[100024];  // Примерное число, которое надо поменять, если требуется! Мне для экспериментов подошло. В дальнейшем можно будет сделать какой-нибудь ByteStream

            // Connect to a remote device.
            try
            {
                string str_first = str.Split(new char[] { '\r', '\n' })[0];
                string[] arr_str_first = str_first.Split(' ');
                string[] arr_str_address = arr_str_first[1].Split('/');
                Uri uri = (new Uri(arr_str_first[1]));
                string new_str_first = arr_str_first[0] + " /" + arr_str_address.Last() + " " + arr_str_first[2];

                // разделить запрос на две части - заголовки и тело:
                string str_headers = str.Substring(str_first.Length + 2, str.IndexOf("\r\n\r\n") - str_first.Length - 2);
                string str_body = str.Substring(str.IndexOf("\r\n\r\n") + 4);

                int index_substring_content_length = str_headers.IndexOf("Content-Length:");
                if (index_substring_content_length >= 0)
                {
                    string tmp = str_headers.Substring(index_substring_content_length);
                    string[] arr_temp = tmp.Split(new char[] { '\r', '\n' });
                    string sub_string_content_length = arr_temp[0];
                    sub_string_content_length = "\r\n" + sub_string_content_length;
                    Regex regex = new Regex(sub_string_content_length);
                    str_headers = regex.Replace(str_headers, "", 1);
                }

                // Establish the remote endpoint for the socket.
                IPHostEntry ipHostInfo = Dns.GetHostEntry(uri.Host);
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, uri.Port);

                // Create a TCP/IP  socket.
                Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // Connect the socket to the remote endpoint. Catch any errors.
                try
                {
                    sender.Connect(remoteEP);

                    Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString());

                    string raw_request = new_str_first+"\r\n"+str_headers+ "\r\nContent-Length: "+ Encoding.UTF8.GetBytes(str_body).Length+"\r\n\r\n"+str_body;

                    // Encode the data string into a byte array.
                    byte[] msg = Encoding.UTF8.GetBytes(raw_request); // + "<Client Quit>");

                    // Send the data through the socket.
                    int bytesSent = sender.Send(msg);
                    Console.WriteLine("bytesSent = {0}", bytesSent.ToString());

                    // Receive the response from the remote device.
                    int bytesRec = sender.Receive(bytes); 
                    Console.WriteLine("Echoed test = {0}", Encoding.UTF8.GetString(bytes, 0, bytesRec)); // bytesRec));

                    // Release the socket.
                    sender.Shutdown(SocketShutdown.Both);
                    sender.Close();

                }
                catch (ArgumentNullException ane)
                {
                    Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
                }
                catch (SocketException se)
                {
                    Console.WriteLine("SocketException : {0}", se.ToString());
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Unexpected exception : {0}", ex.ToString());
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

Here is the result that should have been received in the response from the server:
Result received.
PS
I understood why it did not work from the very beginning. After looking at how Fiddler2 handled the query syntax in the Composer section quite freely, I thought that I could do it too. But, most likely, in the background, Fiddler2 still processes the request, trying to bring it as close to the standard as possible. Here is an example of the difference between what is written in the Composer and what the Inspector shows:
cbe1feb2544f445e8b99fa03a5f306eb.png

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question