IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Protocoles Discussion :

HTTP header : longueur de "Content-length"


Sujet :

Protocoles

  1. #1
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut HTTP header : longueur de "Content-length"
    Bonjour,

    Ma question concerne le format des header HTTP

    Je programme des petit serveurs et des petits clients HTTP en C++ sur des cartes embarquées

    Avec mon serveur, je dois créer un header HTTP avant ma payload :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf_P(Buffer_HTTP, PSTR("HTTP/1.1 200 OK\r\nContent-type: text/html\r\nContent-length: %d\r\nConnection: close\r\n\r\n"), len);
    La longueur 'len', qui est le paramètre affiché après "Content-length:" à la place du '%d', est un nombre qui sera imprimé dans la chaine de caractères en décimal, et que ce nombre peut occuper :
    - un caractère (si len est compris de 0 à 9)
    - deux caractères (si len est compris de 10 à 99)
    ...

    Mon soucis est que je ne peut connaitre la valeur de 'Content-length:' qu'une fois que j'ai généré toute ma réponse.

    Et la longueur de mon header HTTP dépend donc de la valeur de la longueur de 'Content-length:'

    Ca serait plus simple si cette valeur était codée sur 16 bits ces satanés "nombres en texte" c'est bien pour les humains, pas pour le codage

    Pour résoudre le problème j'utilise un buffer, dans lequel j'écris ma réponse avec un offset qui laisse assez de place pour contenir le header + un 'Content-length:' de 4 caractères

    Ensuite une fois que je connais le 'Content-length:', je peut écrire le header HTTP avec un offset de 0, 1, 2 ou 3 caractères (0 si 'Content-length:' occupe 4 caractères, 3 si 'Content-length:' occupe 1 caractère)

    Enfin, je peux envoyer la réponse au client avec un offset de 0, 1, 2 ou 3 caractères

    Cette façon de faire est très lourde.

    Elle m'oblige à stocker toute la réponse avec le header dans un gros buffer dans la RAM de mon microcontroleur, alors que je pourrais envoyer à la puce de la carte réseau les données aux fur et à mesure (la puce de la carte réseau a en fait plus de RAM que mon microcontroleur)

    La question que je me pose est s'il est possible de préciser une valeur de 'Content-length:' avec des espaces et/ou des zéros non significatifs, par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "HTTP/1.1 200 OK\r\nContent-type: text/html\r\nContent-length: 0001\r\nConnection: close\r\n\r\n"
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "HTTP/1.1 200 OK\r\nContent-type: text/html\r\nContent-length:    1\r\nConnection: close\r\n\r\n"
    Je souhaite que la page générée soit conforme W3C pour garantir qu'elle sera correctement affichée quelque soit le client.
    Sinon, ça serait trop facile et moins drôle

    Merci

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  2. #2
    Membre expérimenté Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    623
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 623
    Points : 1 551
    Points
    1 551
    Par défaut
    Hello,

    sprintf(str,"%04d",len) permet d'avoir toujours 4 caractères dans str: len=1 → str=0001, len=25 → str=0025, ect...
    On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent

  3. #3
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Citation Envoyé par edgarjacobs Voir le message
    sprintf(str,"%04d",len) permet d'avoir toujours 4 caractères dans str: len=1 → str=0001, len=25 → str=0025, ect...
    Oui, je sais bien

    Mais ma question c'est de savoir si d'un point de vue "W3C" il est acceptable d'avoir "Content-length: 0009" à la place de "Content-length: 9"

    J'ai peur que des clients n'aiment pas cette façon de faire et refusent d'afficher ma page.

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  4. #4
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonjour,

    En fait ce type de question est un peut ennuyeux, car on ne sait pas trop sur quel forum les poster...

    Je pense que ce forum est plus adapté : https://www.developpez.net/forums/f1...ux/protocoles/

    Je ne sais pas comment déplacer mon message ; peut-être que seuls les modérateurs peuvent le faire

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    Je vois pas trop où est le problème.
    Génère tout, puis utilise strlen pour connaître la taille des chaînes générées.
    Puis tu envois ce qu'il faut ou repack le tout dans le bon ordre.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonjour,

    Mon soucis est que mon code n'est pas sur un ordinateur, mais sur un modeste microcontrôleur.

    La RAM est limitée, avoir un "gros buffer" de plus de 1000 octets c'est compliqué

    De même, chaque fonction en plus pour manipuler des chaines de caractères "coute" des octets de ROM.
    Quand on a réussi à faire un code optimisé, et qu'à la fin il faut inclure une ou deux bibliothèques avec tout un tas de fonctions de manipulations de chaines de caractères juste pour lire ou envoyer un paramètre c'est rageant.

    Ca n'a l'air de rien mais c'est très emmerdant que la taille, qui doit être écrite en premier, mais qui ne peux être connue qu'en dernier, soit codée sur un nombre d'octets dont le nombre peut varier.

    Comme expliqué, les nombres écrits en chaine de caractères c'est l'enfer :
    - ça bouffe de la place ("M=302&" bouffe 6 octets, avec un codage fixe en binaire c'est deux octets)
    - le nombre d'octets n'est pas fixe
    - à l'émission il faut convertir le nombre en chaine de caractères
    - à la réception il faut "parser" la chaine de caractères pour la convertir en nombre
    - sans oublier toute la tartine de tests pour gérer les cas où la chaine de caractère reçue n'est pas correcte

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  7. #7
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Il y a une solution : envoyer si nécessaire à la fin des données des octets de "bourrage" inutiles pour avoir une longueur toujours supérieure à 1000.
    De cette façon, la longueur s'écrira toujours avec 4 caractères

    C'est la méthode bourrin dans toute sa splendeur - une petite boucle for, ça coûte pas grand chose en ROM ni en RAM

    Cette façon de faire est très vilaine c'est du gâchis de bande passante

    Mais "c'est pas grave aujourd'hui de gâcher quelques centaines d'octets inutiles à chaque connection"

    Oui mais non ... je refuse de faire ça
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    Ben HTTP c'est tout du protocole texte, donc oui c'est jamais optimisé.
    Quel est le problème réel ?
    Connais-tu la taille du payload au moment où tu crées le header ?
    Dans ce cas, qu'est-ce qui t'empêches de l'écrire directement dans le header ?
    Si non, et que tu ne veux pas non plus le stocker pendant que tu écris le header, je vois difficilement comment tu espères t'en sortir.
    Si c'est juste pour prévoir l'espace dans le header, prend le pire cas, prévois X octets, puis tu assignes la valeur réelle et memmove le reste du header pour packer le tout. Ou laisse des espaces en trop dans le header, je pense pas que http t'en tienne rigueur (ils sont généralement souples sur les espaces).
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Connais-tu la taille du payload au moment où tu crées le header ?
    Non, justement c'est ça le problème

    Mon microcontrôleur envoi les données via un bus SPI à une sorte de petite carte réseau.

    Cette carte réseau peut gérer 8 sockets qui ont chacun 2ko de RAM pour le buffer TX et 2ko de RAM pour le buffer RX

    Mon microcontrôleur a 2ko de RAM.
    Hé oui, la carte réseau "périphérique" est plus puissante que le microcontrôleur au centre du projet !
    (Un peu comme les cartes graphiques pour le minage de bitcoins vis à vis des CPU )

    Donc j'écris les données en plusieurs étapes dans le buffer du socket de la carte réseau que j'utilise, ça permet d'économiser la RAM du microcontrôleur

    Malheureusement, je ne peut pas faire de "memmove" dans le buffer du socket de la carte réseau *

    Donc, je dois utiliser la RAM du microcontrôleur :
    - je créé un buffer assez grand
    - je commence par écrire ma payload dans ce buffer avec un offset correspondant à la longueur maxi du header (c'est à dire un header avec un content-lenght sur 4 caractères)
    - une fois que je connais la taille de ma payload, je sais combien de caractères il faut pour content-lenght
    - je peux alors écrire le header avec un offset compris en 0 et 3 octets (cet offset est égale à 4 - le nombre de caractères qu'il faut pour écrire content-lenght)
    - enfin, j'envoie les données dans le buffer du socket de la carte réseau, en tenant compte de ce petit offset de 0 à 3 octets

    Ca fonctionne (mon microcontrôleur génère des pages conformes W3C) mais ça m'oblige à dédier la majeure partie de la RAM du microcontroleur dans un buffer assez grand pour contenir le header et la payload.

    Avoir un header HTTP de longueur fixe quelque soit la valeur de content-lenght me permet d'écrire le buffer du socket de la carte réseau en plusieurs étapes, et donc de ne pas avoir un énorme buffer dans la RAM du microcontroleur.

    Là, je pense que c'est plus clair

    Et oui tu as raison, HTML et HTTP sont des protocoles "verbeux" donc pas très efficaces en termes de rendement pour des données autre que du texte...

    * Cela dit, je n'ai pas épluché la datasheet de la puce de la carte réseau, je me contente d'utiliser les fonctions de la bibliothèque qui est fournie avec, et dont j'ai le code source...
    Si jamais il est possible de demander à la puce de la carte réseau d'envoyer une réponse ou une requête à partir d'un offset du buffer d'un socket, mon problème est résolut.

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    Dans ce cas, option 2 : prévoir un header plus grand, et packer des espaces ou saut de ligne dedans.
    Ton header sera "...content-length: x..x\r\n..." et tu remplaces les x..x par la valeur, puis remplaces les xx restant avec des espaces ou des sauts de ligne.
    Je pense pas que ce sera un problème pour le W3C, le parsing s'arrête sur \r\n (et les espaces devraient être tronqués lors de l'extraction de la valeur décimale si tu décides d'utiliser les espaces).
    Oui tu vas perdre une poignée d'octets de ram/rom, mais je vois pas d'autre solution.
    Et pour connaître la taille de la représentation en string d'un nombre, tu peux utiliser un log de base 10.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    OK je vais tester pour voir si W3C accepte

    Je me méfie car autant le navigateur google chrome est très tolérant sur le HTML, dès qu'il y a un truc qui va pas dans le header la page ne s'affiche pas où le navigateur me refait des requêtes supplémentaires.

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  12. #12
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonjour,

    Alors bonne nouvelle, google Chrome et le validateur W3C acceptent des headers avec des zéro non significatifs

    Exemple de header :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    HTTP/1.1 200 OK
    Content-type: text/html
    Content-length: 0098
    Connection: close
    
    <!DOCTYPE html><HTML>....</HTML>
    Ca va simplifier les choses.

    Il suffit d'écrire le header de cette façon, à l'offset '0' dans le le buffer du socket de la carte réseau

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    sprintf_P(Buffer_HTTP, PSTR("HTTP/1.1 200 OK\r\nContent-type: text/html\r\nContent-length: %04d\r\nConnection: close\r\n\r\n"), len);
    mysocket.write(Buffer_HTTP,0);
    Sachant que auparavant on aura écrit la payload à l'offset 85, étant donné que la chaine "HTTP/1.1 200 OK\r\nContent-type: text/html\r\nContent-length: 0000\r\nConnection: close\r\n\r\n" occupe les octets de 0 à 84

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec "Content-Length" HTTP
    Par n5Rzn1D9dC dans le forum Développement
    Réponses: 1
    Dernier message: 07/12/2013, 13h31
  2. Requetes Headers pour Content-Length
    Par DarkVader dans le forum Langages serveur
    Réponses: 0
    Dernier message: 17/04/2011, 21h04
  3. Réponses: 1
    Dernier message: 10/04/2010, 13h55
  4. [HTTP Header] Content-Size et téléchargement
    Par Hibou57 dans le forum Apache
    Réponses: 1
    Dernier message: 26/07/2006, 02h24
  5. [W3C] HTTP Header et UTF-8
    Par narnou dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 13/03/2006, 12h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo