none
Comment Parser une requête HTTP à partir d'un byte[] ou d'un string ? RRS feed

  • Question

  • Bonjour,

    Je voulais savoir si le Framework .NET 2.0 possède un objet qui permet de ‘parser* ‘ une requête HTTP à partir d’un élément de type byte[] ou string.

    *La méthode de parser permet de décomposer l’en-tête HTTP en plusieurs champs tel que la méthode HTTP, le code réponse, le type de message, le contenu du message ainsi que sa taille (etc…) selon RFC (http://www.ietf.org/rfc/rfc2616.txt)

    Je me suis dans un premier temps orienté vers les objets :

    HttpListener
    pour les requêtes reçues et WebResponse pour les requêtes envoyées.
    Cependant, ces derniers ne répondent pas à mes attentes.
    En effet, bien que ces objets effectues la décomposition de l’en-tête HTTP, ils n’ont aucune méthode permettant d’effectuer la conversion depuis un élément de type byte[] ou string.

    Peut être existe-t-il un moyen de convertir mes éléments en objet pris en compte par HttpListener (mais je n’ai pas encore trouvé comment).

    Merci d’avance.

    samedi 24 octobre 2009 14:47

Réponses

  • Finalement, j'ai créer une classe qui me permet de parser la requête HTTP dont voici le code :

    namespace HTTPParserConsole
    {
        public enum HTTPHeaderField
        {
            Accept = 0,
            Accept_Charset = 1,
            Accept_Encoding = 2,
            Accept_Language = 3,
            Accept_Ranges = 4,
            Authorization = 5,
            Cache_Control = 6,
            Connection = 7,
            Cookie = 8,
            Content_Length = 9,
            Content_Type = 10,
            Date = 11,
            Expect = 12,
            From = 13,
            Host = 14,
            If_Match = 15,
            If_Modified_Since = 16,
            If_None_Match = 17,
            If_Range = 18,
            If_Unmodified_Since = 19,
            Max_Forwards = 20,
            Pragma = 21,
            Proxy_Authorization = 22,
            Range = 23,
            Referer = 24,
            TE = 25,
            Upgrade = 26,
            User_Agent = 27,
            Via = 28,
            Warn = 29,
            Age = 30,
            Allow = 31,
            Content_Encoding = 32,
            Content_Language = 33,
            Content_Location = 34,
            Content_Disposition = 35,
            Content_MD5 = 36,
            Content_Range = 37,
            ETag = 38,
            Expires = 39,
            Last_Modified = 40,
            Location = 41,
            Proxy_Authenticate = 42,
            Refresh = 43,
            Retry_After = 44,
            Server = 45,
            Set_Cookie = 46,
            Trailer = 47,
            Transfer_Encoding = 48,
            Vary = 49,
            Warning = 50,
            WWW_Authenticate = 51
        };
    
    
        class HTTPHeader
        {
            #region PROPERTIES
            private string[] m_StrHTTPField = new string[52];
            private byte[] m_byteData = new byte[4096];
    
            public string[] HTTPField
            {
                get { return m_StrHTTPField; }
                set { m_StrHTTPField = value; }
            }
            public byte[] Data
            {
                get { return m_byteData; }
                set { m_byteData = value; }
            }
            #endregion
            // convertion
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    
    
            #region CONSTRUCTEUR
            /// <summary>
            /// Constructeur par défaut - non utilisé
            /// </summary>
            private HTTPHeader()
            { }
    
            public HTTPHeader(string HTTPRequest)
            {
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                    {
                        Header = HTTPRequest;
                    }
                    else {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
                    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
    
            public HTTPHeader(byte[] ByteHTTPRequest)
            {
                string HTTPRequest = encoding.GetString(ByteHTTPRequest);
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                        Header = HTTPRequest;
                    else
                    {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        //Data = HTTPRequest.Substring(IndexHeaderEnd + 4);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
            #endregion
    
            #region METHODES
            private void HTTPHeaderParse(string Header)
            {
                #region HTTP HEADER REQUEST & RESPONSE
    
                HTTPHeaderField HHField;
                string HTTPfield, buffer;
                int Index;
                foreach (int IndexHTTPfield in Enum.GetValues(typeof(HTTPHeaderField)))
                {
                    HHField = (HTTPHeaderField)IndexHTTPfield;
                    HTTPfield = "\n" + HHField.ToString().Replace('_', '-') + ": "; //Ajout de \n devant pour éviter les doublons entre cookie et set_cookie / ou entre accepte et accepte-etc...
    
                    // Si le champ n'est pas présent dans la requête, on passe au champ suivant
                    Index = Header.IndexOf(HTTPfield);
                    if (Index == -1)
                        continue;
    
                    buffer = Header.Substring(Index + HTTPfield.Length);
                    Index = buffer.IndexOf("\r\n");
                    if (Index == -1)
                        m_StrHTTPField[IndexHTTPfield] = buffer.Trim();
                    else
                        m_StrHTTPField[IndexHTTPfield] = buffer.Substring(0, Index).Trim();
    
                    Console.WriteLine("Index = " + IndexHTTPfield + " | champ = " + HTTPfield.Substring(1) + " " + m_StrHTTPField[IndexHTTPfield]);
                }
                
                // Affichage de tout les champs
                /*for (int j = 0; j < m_StrHTTPField.Length; j++)
                {
                    HHField = (HTTPHeaderField)j;
                    Console.WriteLine("m_StrHTTPField[" + j + "]; " + HHField + " = " + m_StrHTTPField[j]);
                }
                */
                #endregion
    
            }
            #endregion
        }
    }
    
    Pour l'utiliser :
    PS : Je n'ai pas pu mettre de vraies requête dans l'exemple ci-dessous car le forum rencontre une erreur avec les caractère d'une "vraie requête HTTP".
    Donc, pour le tester, récupérer une requête et coller le :
    static void Main(string[] args)
            {
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.Title = "HTTP Parser Console";
    
               //Copier coller une VRAIE requête HTTP
     string Requete = "GET .........."; string Response = "HTTP/1.1 200 OK ..."; HTTPHeader HHRequest = new HTTPHeader(Requete); HTTPHeader HHResponse = new HTTPHeader(Response); // J'ai vérifier que le découpage entre le header et les données était bien correct : Console.WriteLine("HHResponse Content Length = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Length]); Console.WriteLine("HHResponse Data Length = " + HHResponse.Data.GetLength(0).ToString()); // Exemple de récupération d'un champ du HTTP header : Console.WriteLine("HHResponse Type = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Type]); Console.WriteLine("Fin du programme"); Console.ReadKey(true); }
    Voilà voilà, en espérant que ce morceau de code peut en aidé certains.

    Cordialement,
    ShellDone.


    • Marqué comme réponse ShellDone dimanche 25 octobre 2009 15:01
    dimanche 25 octobre 2009 14:58

Toutes les réponses

  • Bonjour,

    Utilisez la méthode Encoding.GetString() :
    http://msdn.microsoft.com/en-us/library/744y86tc.aspx

    Cordialement
    Gilles TOURREAU - MVP C# - Architecte .NET/Consultant/Formateur
    dimanche 25 octobre 2009 09:13
    Modérateur
  • Merci Gilles pour cette réponse.
    Cependant, cela ne répond pas à ma question, en effet, mon souci n'est pas la version d'une requête byte[] en string mais plutôt comment parser une requête de type string;
    Exemple :
    string Requete = "GET /Forums/fr-FR/visualcsharpfr/threads?since=2009-10-31T14%3A47%3A36.8100000Z HTTP/1.1\r\nHost: social.msdn.microsoft.com\r\nUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3\r\nAccept: */*\r\nAccept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection: keep-alive\r\nX-Requested-With: XMLHttpRequest\r\nReferer: http://social.msdn.microsoft.com/Forums/fr-FR/visualcsharpfr/threads\r\nCookie: MC1=GUID=09c9c0f801745720a84a2ad2e9b63054&HASH=09a9&LV=200911&V=1; WT_FPC=id=192.168.1.1-4043517736.2009994:lv=1256393252087:ss=1256323211374; A=I&I=AxUFAAAAAADkAAa8zVx5xPxKatgrqMNr29hA!!&CS=123F4B00013xO0302h3xO0301MBli0002I0Sq0001[1X:00&M=1; WT_NVR_RU=0=msdn|technet:1=:2=; WT_NVR=0=/:1=fr-fr:2=fr-fr/library|en-us/library|fr-fr/express|fr-fr/magazine|fr-fr/vcsharp|fr-fr/vstudio; MUID=B7D70D90FFE34F9C8A80789C158CA696; omniID=1246400814938_de3e_58b3_40b7_9d7663267073; msresearch=1; .ASPXANONYMOUS=jf5dtvdvywEkAAAAFGDFDQSDNy00YjExLTlmZDAtYjFhNmE2ZWFkZTcyLLqJlsBahe-aybY3nniScjaUoBw1";

    Donne :
    Méthode : GET
    Host : social.msdn.microsoft.com
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3
    Accept: */*
    Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
    Accept-Encoding: gzip,deflate\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive

    Cordialement
    dimanche 25 octobre 2009 12:29
  • Finalement, j'ai créer une classe qui me permet de parser la requête HTTP dont voici le code :

    namespace HTTPParserConsole
    {
        public enum HTTPHeaderField
        {
            Accept = 0,
            Accept_Charset = 1,
            Accept_Encoding = 2,
            Accept_Language = 3,
            Accept_Ranges = 4,
            Authorization = 5,
            Cache_Control = 6,
            Connection = 7,
            Cookie = 8,
            Content_Length = 9,
            Content_Type = 10,
            Date = 11,
            Expect = 12,
            From = 13,
            Host = 14,
            If_Match = 15,
            If_Modified_Since = 16,
            If_None_Match = 17,
            If_Range = 18,
            If_Unmodified_Since = 19,
            Max_Forwards = 20,
            Pragma = 21,
            Proxy_Authorization = 22,
            Range = 23,
            Referer = 24,
            TE = 25,
            Upgrade = 26,
            User_Agent = 27,
            Via = 28,
            Warn = 29,
            Age = 30,
            Allow = 31,
            Content_Encoding = 32,
            Content_Language = 33,
            Content_Location = 34,
            Content_Disposition = 35,
            Content_MD5 = 36,
            Content_Range = 37,
            ETag = 38,
            Expires = 39,
            Last_Modified = 40,
            Location = 41,
            Proxy_Authenticate = 42,
            Refresh = 43,
            Retry_After = 44,
            Server = 45,
            Set_Cookie = 46,
            Trailer = 47,
            Transfer_Encoding = 48,
            Vary = 49,
            Warning = 50,
            WWW_Authenticate = 51
        };
    
    
        class HTTPHeader
        {
            #region PROPERTIES
            private string[] m_StrHTTPField = new string[52];
            private byte[] m_byteData = new byte[4096];
    
            public string[] HTTPField
            {
                get { return m_StrHTTPField; }
                set { m_StrHTTPField = value; }
            }
            public byte[] Data
            {
                get { return m_byteData; }
                set { m_byteData = value; }
            }
            #endregion
            // convertion
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    
    
            #region CONSTRUCTEUR
            /// <summary>
            /// Constructeur par défaut - non utilisé
            /// </summary>
            private HTTPHeader()
            { }
    
            public HTTPHeader(string HTTPRequest)
            {
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                    {
                        Header = HTTPRequest;
                    }
                    else {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
                    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
    
            public HTTPHeader(byte[] ByteHTTPRequest)
            {
                string HTTPRequest = encoding.GetString(ByteHTTPRequest);
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                        Header = HTTPRequest;
                    else
                    {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        //Data = HTTPRequest.Substring(IndexHeaderEnd + 4);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
            #endregion
    
            #region METHODES
            private void HTTPHeaderParse(string Header)
            {
                #region HTTP HEADER REQUEST & RESPONSE
    
                HTTPHeaderField HHField;
                string HTTPfield, buffer;
                int Index;
                foreach (int IndexHTTPfield in Enum.GetValues(typeof(HTTPHeaderField)))
                {
                    HHField = (HTTPHeaderField)IndexHTTPfield;
                    HTTPfield = "\n" + HHField.ToString().Replace('_', '-') + ": "; //Ajout de \n devant pour éviter les doublons entre cookie et set_cookie / ou entre accepte et accepte-etc...
    
                    // Si le champ n'est pas présent dans la requête, on passe au champ suivant
                    Index = Header.IndexOf(HTTPfield);
                    if (Index == -1)
                        continue;
    
                    buffer = Header.Substring(Index + HTTPfield.Length);
                    Index = buffer.IndexOf("\r\n");
                    if (Index == -1)
                        m_StrHTTPField[IndexHTTPfield] = buffer.Trim();
                    else
                        m_StrHTTPField[IndexHTTPfield] = buffer.Substring(0, Index).Trim();
    
                    Console.WriteLine("Index = " + IndexHTTPfield + " | champ = " + HTTPfield.Substring(1) + " " + m_StrHTTPField[IndexHTTPfield]);
                }
                
                // Affichage de tout les champs
                /*for (int j = 0; j < m_StrHTTPField.Length; j++)
                {
                    HHField = (HTTPHeaderField)j;
                    Console.WriteLine("m_StrHTTPField[" + j + "]; " + HHField + " = " + m_StrHTTPField[j]);
                }
                */
                #endregion
    
            }
            #endregion
        }
    }
    
    Pour l'utiliser :
    static void Main(string[] args)
            {
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.Title = "HTTP Parser Console";
    
               //Copier coller une requête
                string Requete = "GET ..........";
                string Response = "HTTP/1.1 200 OK\r\nCache-Control: private\r\nContent-Type: text/html; charset=utf-8\r\nExpires: Sat, 31 Oct 2009 06:06:06 GMT\r\nServer: Microsoft-IIS/7.0\r\nSet-Cookie: msdn=L=1036; path=/\r\nX-AspNetMvc-Version: 1.0\r\nX-AspNet-Version: 2.0.50727\r\nX-Powered-By: ASP.NET\r\nP3P: CP=ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\r\nServer: CO1VB23\r\nDate: Sat, 31 Oct 2009 06:06:06 GMT\r\nContent-Encoding: gzip\r\nContent-Length:        121\r\n\r\n\b......0³)°s,M.ÍS(É(JMsqfdLQ()Ê/-;¼ÒF¿ÀqsdfË&3¯ ´D!/17ÕV©$37µ¸$1·@I¡¤².(a4813‘™näXêèX[$*ù$^ù*ù$^$ù*¾.±¤kÒj...";
    
                HTTPHeader HHRequest = new HTTPHeader(Requete);
                HTTPHeader HHResponse = new HTTPHeader(Response);
    
                // J'ai vérifier que le découpage entre le header et les données était bien correct : 
                Console.WriteLine("HHResponse Content Length = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Length]);
                Console.WriteLine("HHResponse Data Length = " + HHResponse.Data.GetLength(0).ToString());
    
                // Exemple de récupération d'un champ du HTTP header : 
                Console.WriteLine("HHResponse Type = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Type]);
    
                Console.WriteLine("Fin du programme");
                Console.ReadKey(true);
            }
    Voilà voilà, en espérant que ce morceau de code peut en aidé certains.

    Cordialement,
    ShellDone.


    dimanche 25 octobre 2009 14:57
  • Finalement, j'ai créer une classe qui me permet de parser la requête HTTP dont voici le code :

    namespace HTTPParserConsole
    {
        public enum HTTPHeaderField
        {
            Accept = 0,
            Accept_Charset = 1,
            Accept_Encoding = 2,
            Accept_Language = 3,
            Accept_Ranges = 4,
            Authorization = 5,
            Cache_Control = 6,
            Connection = 7,
            Cookie = 8,
            Content_Length = 9,
            Content_Type = 10,
            Date = 11,
            Expect = 12,
            From = 13,
            Host = 14,
            If_Match = 15,
            If_Modified_Since = 16,
            If_None_Match = 17,
            If_Range = 18,
            If_Unmodified_Since = 19,
            Max_Forwards = 20,
            Pragma = 21,
            Proxy_Authorization = 22,
            Range = 23,
            Referer = 24,
            TE = 25,
            Upgrade = 26,
            User_Agent = 27,
            Via = 28,
            Warn = 29,
            Age = 30,
            Allow = 31,
            Content_Encoding = 32,
            Content_Language = 33,
            Content_Location = 34,
            Content_Disposition = 35,
            Content_MD5 = 36,
            Content_Range = 37,
            ETag = 38,
            Expires = 39,
            Last_Modified = 40,
            Location = 41,
            Proxy_Authenticate = 42,
            Refresh = 43,
            Retry_After = 44,
            Server = 45,
            Set_Cookie = 46,
            Trailer = 47,
            Transfer_Encoding = 48,
            Vary = 49,
            Warning = 50,
            WWW_Authenticate = 51
        };
    
    
        class HTTPHeader
        {
            #region PROPERTIES
            private string[] m_StrHTTPField = new string[52];
            private byte[] m_byteData = new byte[4096];
    
            public string[] HTTPField
            {
                get { return m_StrHTTPField; }
                set { m_StrHTTPField = value; }
            }
            public byte[] Data
            {
                get { return m_byteData; }
                set { m_byteData = value; }
            }
            #endregion
            // convertion
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    
    
            #region CONSTRUCTEUR
            /// <summary>
            /// Constructeur par défaut - non utilisé
            /// </summary>
            private HTTPHeader()
            { }
    
            public HTTPHeader(string HTTPRequest)
            {
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                    {
                        Header = HTTPRequest;
                    }
                    else {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
                    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
    
            public HTTPHeader(byte[] ByteHTTPRequest)
            {
                string HTTPRequest = encoding.GetString(ByteHTTPRequest);
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                        Header = HTTPRequest;
                    else
                    {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        //Data = HTTPRequest.Substring(IndexHeaderEnd + 4);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
            #endregion
    
            #region METHODES
            private void HTTPHeaderParse(string Header)
            {
                #region HTTP HEADER REQUEST & RESPONSE
    
                HTTPHeaderField HHField;
                string HTTPfield, buffer;
                int Index;
                foreach (int IndexHTTPfield in Enum.GetValues(typeof(HTTPHeaderField)))
                {
                    HHField = (HTTPHeaderField)IndexHTTPfield;
                    HTTPfield = "\n" + HHField.ToString().Replace('_', '-') + ": "; //Ajout de \n devant pour éviter les doublons entre cookie et set_cookie / ou entre accepte et accepte-etc...
    
                    // Si le champ n'est pas présent dans la requête, on passe au champ suivant
                    Index = Header.IndexOf(HTTPfield);
                    if (Index == -1)
                        continue;
    
                    buffer = Header.Substring(Index + HTTPfield.Length);
                    Index = buffer.IndexOf("\r\n");
                    if (Index == -1)
                        m_StrHTTPField[IndexHTTPfield] = buffer.Trim();
                    else
                        m_StrHTTPField[IndexHTTPfield] = buffer.Substring(0, Index).Trim();
    
                    Console.WriteLine("Index = " + IndexHTTPfield + " | champ = " + HTTPfield.Substring(1) + " " + m_StrHTTPField[IndexHTTPfield]);
                }
                
                // Affichage de tout les champs
                /*for (int j = 0; j < m_StrHTTPField.Length; j++)
                {
                    HHField = (HTTPHeaderField)j;
                    Console.WriteLine("m_StrHTTPField[" + j + "]; " + HHField + " = " + m_StrHTTPField[j]);
                }
                */
                #endregion
    
            }
            #endregion
        }
    }
    
    Pour l'utiliser :
    static void Main(string[] args)
            {
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.Title = "HTTP Parser Console";
    
               //Copier coller une requête
                string Requete = "GET ..........";
                string Response = "HTTP/1.1 200 OK\r\nCache-Control: private\r\nContent-Type: text/html; charset=utf-8\r\nExpires: Sat, 31 Oct 2009 06:06:06 GMT\r\nServer: Microsoft-IIS/7.0\r\nSet-Cookie: msdn=L=1036; path=/\r\nX-AspNetMvc-Version: 1.0\r\nX-AspNet-Version: 2.0.50727\r\nX-Powered-By: ASP.NET\r\nP3P: CP=ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\r\nServer: CO1VB23\r\nDate: Sat, 31 Oct 2009 06:06:06 GMT\r\nContent-Encoding: gzip\r\nContent-Length:        121\r\n\r\n\b......0³)°s,M.ÍS(É(JMsqfdLQ()Ê/-;¼ÒF¿ÀqsdfË&3¯ ´D!/17ÕV©$37µ¸$1·@I¡¤².(a4813‘™näXêèX[$*ù$^ù*ù$^$ù*¾.±¤kÒj...";
    
                HTTPHeader HHRequest = new HTTPHeader(Requete);
                HTTPHeader HHResponse = new HTTPHeader(Response);
    
                // J'ai vérifier que le découpage entre le header et les données était bien correct : 
                Console.WriteLine("HHResponse Content Length = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Length]);
                Console.WriteLine("HHResponse Data Length = " + HHResponse.Data.GetLength(0).ToString());
    
                // Exemple de récupération d'un champ du HTTP header : 
                Console.WriteLine("HHResponse Type = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Type]);
    
                Console.WriteLine("Fin du programme");
                Console.ReadKey(true);
            }
    Voilà voilà, en espérant que ce morceau de code peut en aidé certains.

    Cordialement,
    ShellDone.


    dimanche 25 octobre 2009 14:57
  • Finalement, j'ai créer une classe qui me permet de parser la requête HTTP dont voici le code :

    namespace HTTPParserConsole
    {
        public enum HTTPHeaderField
        {
            Accept = 0,
            Accept_Charset = 1,
            Accept_Encoding = 2,
            Accept_Language = 3,
            Accept_Ranges = 4,
            Authorization = 5,
            Cache_Control = 6,
            Connection = 7,
            Cookie = 8,
            Content_Length = 9,
            Content_Type = 10,
            Date = 11,
            Expect = 12,
            From = 13,
            Host = 14,
            If_Match = 15,
            If_Modified_Since = 16,
            If_None_Match = 17,
            If_Range = 18,
            If_Unmodified_Since = 19,
            Max_Forwards = 20,
            Pragma = 21,
            Proxy_Authorization = 22,
            Range = 23,
            Referer = 24,
            TE = 25,
            Upgrade = 26,
            User_Agent = 27,
            Via = 28,
            Warn = 29,
            Age = 30,
            Allow = 31,
            Content_Encoding = 32,
            Content_Language = 33,
            Content_Location = 34,
            Content_Disposition = 35,
            Content_MD5 = 36,
            Content_Range = 37,
            ETag = 38,
            Expires = 39,
            Last_Modified = 40,
            Location = 41,
            Proxy_Authenticate = 42,
            Refresh = 43,
            Retry_After = 44,
            Server = 45,
            Set_Cookie = 46,
            Trailer = 47,
            Transfer_Encoding = 48,
            Vary = 49,
            Warning = 50,
            WWW_Authenticate = 51
        };
    
    
        class HTTPHeader
        {
            #region PROPERTIES
            private string[] m_StrHTTPField = new string[52];
            private byte[] m_byteData = new byte[4096];
    
            public string[] HTTPField
            {
                get { return m_StrHTTPField; }
                set { m_StrHTTPField = value; }
            }
            public byte[] Data
            {
                get { return m_byteData; }
                set { m_byteData = value; }
            }
            #endregion
            // convertion
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    
    
            #region CONSTRUCTEUR
            /// <summary>
            /// Constructeur par défaut - non utilisé
            /// </summary>
            private HTTPHeader()
            { }
    
            public HTTPHeader(string HTTPRequest)
            {
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                    {
                        Header = HTTPRequest;
                    }
                    else {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
                    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
    
            public HTTPHeader(byte[] ByteHTTPRequest)
            {
                string HTTPRequest = encoding.GetString(ByteHTTPRequest);
                try
                {
                    int IndexHeaderEnd;
                    string Header;
    
                    // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http
                    if (HTTPRequest.Length >= 1460)
                        Header = HTTPRequest;
                    else
                    {
                        IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n");
                        Header = HTTPRequest.Substring(0, IndexHeaderEnd);
                        //Data = HTTPRequest.Substring(IndexHeaderEnd + 4);
                        Data = encoding.GetBytes(HTTPRequest.Substring(IndexHeaderEnd + 4));
                    }
    
                    HTTPHeaderParse(Header);
                }
                catch (Exception)
                { }
            }
            #endregion
    
            #region METHODES
            private void HTTPHeaderParse(string Header)
            {
                #region HTTP HEADER REQUEST & RESPONSE
    
                HTTPHeaderField HHField;
                string HTTPfield, buffer;
                int Index;
                foreach (int IndexHTTPfield in Enum.GetValues(typeof(HTTPHeaderField)))
                {
                    HHField = (HTTPHeaderField)IndexHTTPfield;
                    HTTPfield = "\n" + HHField.ToString().Replace('_', '-') + ": "; //Ajout de \n devant pour éviter les doublons entre cookie et set_cookie / ou entre accepte et accepte-etc...
    
                    // Si le champ n'est pas présent dans la requête, on passe au champ suivant
                    Index = Header.IndexOf(HTTPfield);
                    if (Index == -1)
                        continue;
    
                    buffer = Header.Substring(Index + HTTPfield.Length);
                    Index = buffer.IndexOf("\r\n");
                    if (Index == -1)
                        m_StrHTTPField[IndexHTTPfield] = buffer.Trim();
                    else
                        m_StrHTTPField[IndexHTTPfield] = buffer.Substring(0, Index).Trim();
    
                    Console.WriteLine("Index = " + IndexHTTPfield + " | champ = " + HTTPfield.Substring(1) + " " + m_StrHTTPField[IndexHTTPfield]);
                }
                
                // Affichage de tout les champs
                /*for (int j = 0; j < m_StrHTTPField.Length; j++)
                {
                    HHField = (HTTPHeaderField)j;
                    Console.WriteLine("m_StrHTTPField[" + j + "]; " + HHField + " = " + m_StrHTTPField[j]);
                }
                */
                #endregion
    
            }
            #endregion
        }
    }
    
    Pour l'utiliser :
    PS : Je n'ai pas pu mettre de vraies requête dans l'exemple ci-dessous car le forum rencontre une erreur avec les caractère d'une "vraie requête HTTP".
    Donc, pour le tester, récupérer une requête et coller le :
    static void Main(string[] args)
            {
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.Title = "HTTP Parser Console";
    
               //Copier coller une VRAIE requête HTTP
     string Requete = "GET .........."; string Response = "HTTP/1.1 200 OK ..."; HTTPHeader HHRequest = new HTTPHeader(Requete); HTTPHeader HHResponse = new HTTPHeader(Response); // J'ai vérifier que le découpage entre le header et les données était bien correct : Console.WriteLine("HHResponse Content Length = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Length]); Console.WriteLine("HHResponse Data Length = " + HHResponse.Data.GetLength(0).ToString()); // Exemple de récupération d'un champ du HTTP header : Console.WriteLine("HHResponse Type = " + HHResponse .HTTPField[(int)HTTPHeaderField.Content_Type]); Console.WriteLine("Fin du programme"); Console.ReadKey(true); }
    Voilà voilà, en espérant que ce morceau de code peut en aidé certains.

    Cordialement,
    ShellDone.


    • Marqué comme réponse ShellDone dimanche 25 octobre 2009 15:01
    dimanche 25 octobre 2009 14:58