Page 1 sur 2

Simple Web Server (Unicode)

Publié : lun. 13/févr./2017 19:05
par falsam
Simple Web Serveur est un simple serveur de page HTML statics .

Préalable.
- Purebasic 5.43 (Unicode) Minimum
- HTML et CSS Minimum

Structure du code.
- Lancement du serveur de pages HTML et affichage des connections. ( Procedure Start() )
- Préparation de l'entête HTTP ( Procedure BuildRequestHeader() )
- Traitements des pages demandées par le client* et nvoie des données au client* ( Procedure ProcessRequest() )

* Client = Navigateur

■ Démo http://109.13.115.206:6834/index.html (Open)

Code.

Code : Tout sélectionner

EnableExplicit

Global Title.s = "Simple Server"

Global Port = 6835

Global WWWDirectory.s = "www1/"
Global WWWIndex.s = "index.html"
Global WWWError.s = "error.html"

Global BufferSize = 1024, *Buffer = AllocateMemory(BufferSize), Buffer.s

Global ClientID

Declare Start()                                                 
Declare ProcessRequest()                                         
Declare BuildRequestHeader(*FileContent, FileExtension.s, FileLength)
Declare ClearLog()
Declare Resize()
Declare Exit()                                                  

Start()

;Affichage / Show application
Procedure Start()
  Protected ServerEvent, Result
  
  If Not InitNetwork() 
    MessageRequester(Title, "Can't initialize the network !", 0)
  Else     
    
    ;Création du serveur / Create server 
    If CreateNetworkServer(0, Port)      
      OpenWindow(0, 0, 0, 800, 600, Title, #PB_Window_SystemMenu | #PB_Window_SizeGadget)
      WindowBounds(0, 200, 100, #PB_Ignore, #PB_Ignore) 
      
      EditorGadget(0, 0, 0, 800, 560, #PB_Editor_ReadOnly)
      AddGadgetItem(0, -1, FormatDate("%hh:%mm", Date()) + " | Server listening on port " + Port)
      
      CheckBoxGadget(1, 10, 570, 200, 22, "Show Log") 
      SetGadgetState(1, #PB_Checkbox_Checked)
      
      ButtonGadget(2, 700, 570, 80, 22, "Clear Log")
      
      ;Déclencheur / Trigger
      BindGadgetEvent(2, @ClearLog())
      BindEvent(#PB_Event_SizeWindow, @Resize())
      BindEvent(#PB_Event_CloseWindow, @Exit())
      
      Repeat    
        Repeat : Until WindowEvent() = 0
        
        ServerEvent = NetworkServerEvent()
        If ServerEvent
          ClientID = EventClient()
          Buffer = ""
          Select ServerEvent              
            Case #PB_NetworkEvent_Data 
              Repeat
                FreeMemory(*Buffer)
                *Buffer = AllocateMemory(BufferSize)
                Result = ReceiveNetworkData(ClientID, *Buffer, BufferSize)
                Buffer + PeekS(*Buffer, -1, #PB_UTF8)
              Until Result <> BufferSize
              
              ProcessRequest()
          EndSelect
        Else
          Delay(10)  ; Ne pas saturer le CPU / Don't stole the whole CPU !
        EndIf
      ForEver     
    Else
      MessageRequester(Title, "Error: can't create the server (port " + port + " in use ?)")
    EndIf
  EndIf
EndProcedure

;Demande de traitement / Process Request
Procedure ProcessRequest()
  Protected RequestedFile.s, FileLength
  Protected *FileContent, *Buffer
  
  If Left(Buffer, 3) = "GET"    
    ;Extract page html from "GET /yourpage.html HTTP/1.1"
    RequestedFile = Trim(Mid(StringField(Buffer, 1, "HTTP"), 6))    
    
    If RequestedFile = ""
      RequestedFile = WWWIndex      
    EndIf
    
    ;Mise à jour du log / UPdated log
    If GetGadgetState(1) = #PB_Checkbox_Checked
      AddGadgetItem(0, -1, FormatDate("%hh:%mm", Date()) + " | Client IP " + IPString(GetClientIP(ClientID)) + " load " + RequestedFile) 
    EndIf   
    
    ;Lecture fichier demandé / Read Requested file
    If ReadFile(0, WWWDirectory + RequestedFile, #PB_UTF8)
    ElseIf ReadFile(0, WWWDirectory + WWWError, #PB_UTF8)
    Else
      MessageRequester(Title, "Error: WWW init error")
    EndIf
    FileLength = Lof(0)
                
    ;Initialisation Header HTTP / Init Header HTTP
    *FileContent  = AllocateMemory(FileLength + 200)
    *Buffer = BuildRequestHeader(*FileContent, GetExtensionPart(RequestedFile), FileLength)
    
    ;Ajout contenu fichier / Add file content
    ReadData(0, *Buffer, FileLength)
    CloseFile(0)
    
    ;Envoyer la page HTML au client / Send the HTML page to the client
    SendNetworkData(ClientID, *FileContent, *Buffer - *FileContent + FileLength)
    FreeMemory(*FileContent)
  EndIf  
EndProcedure

;Creation entete HTTP / Create HTTP header
Procedure BuildRequestHeader(*FileBuffer, FileExtension.s, FileLength)
  Protected Week.s = "Sun, Mon,Tue,Wed,Thu,Fri,Sat"
  Protected MonthsOfYear.s = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec" 
  
  Protected DayOfWeek.s = StringField("Sun, Mon,Tue,Wed,Thu,Fri,Sat", DayOfWeek(Date()) + 1, ",")
  Protected Day = Day(Date())
  Protected Month.s = StringField("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", Month(Date()), ",")
  Protected Year.s = Str(Year(Date()))
  Protected Time.s = FormatDate("%hh:%ii:%ss GMT", Date())
  Protected ContentType.s
  Protected Length
  
  ;Definition du content-type / Setup content-type
  ;Ref : https://fr.wikipedia.org/wiki/Type_MIME
  Select LCase(FileExtension)
    Case "html", "" : ContentType = "text/html"
    Case "css"      : ContentType = "text/css"
    Case "js"       : ContentType = "application/javascript" 
    Case "gif"      : ContentType = "image/gif"
    Case "jpg"      : ContentType = "image/jpeg"
    Case "png"      : ContentType = "image/png"
    Case "txt"      : ContentType = "text/plain"
    Case "zip"      : ContentType = "application/zip"
    Case "pdf"      : ContentType = "application/pdf"
    Default         : ContentType = "application/octet-stream" 
  EndSelect  
  
  ;Création entete / Create header
  Length = PokeS(*FileBuffer, "HTTP/1.1 200 OK" + #CRLF$, -1, #PB_UTF8)                                                             : *FileBuffer + Length
  Length = PokeS(*FileBuffer, "Date: " + DayOfWeek + ", " + Day + " " + Month + " " + Year + " " + Time  + #CRLF$, -1, #PB_UTF8)    : *FileBuffer + Length
  Length = PokeS(*FileBuffer, "Server: "+ Title + #CRLF$, -1, #PB_UTF8)                                                             : *FileBuffer + Length
  Length = PokeS(*FileBuffer, "Content-Length: " + Str(FileLength) + #CRLF$, -1, #PB_UTF8)                                          : *FileBuffer + Length
  Length = PokeS(*FileBuffer, "Content-Type: " + ContentType + #CRLF$ + #CRLF$, -1, #PB_UTF8)                                       : *FileBuffer + Length 
  
  ProcedureReturn *FileBuffer
EndProcedure


Procedure ClearLog()
  ClearGadgetItems(0)  
EndProcedure

Procedure Resize()
  Protected Width = WindowWidth(0)
  Protected Height = WindowHeight(0)
  
  ResizeGadget(0, #PB_Ignore, #PB_Ignore, Width, Height-40)
  ResizeGadget(1, #PB_Ignore, Height - 30, #PB_Ignore, #PB_Ignore)
  ResizeGadget(2, Width - 100, Height - 30, #PB_Ignore, #PB_Ignore)
  
EndProcedure

;Sortie  / Exit 
Procedure Exit()
  CloseNetworkServer(0)  
  End
EndProcedure
Que faire ensuite ?
- Enregistrer le code dans un dossier
- Créer un dossier www
- Coder la page index.html
- Coder la page error.html
- Lancer le serveur
- Coder d'autres pages.
- Laisser des commentaire ^^.

Re: Simple Web Server

Publié : lun. 13/févr./2017 19:13
par Kwai chang caine
Tiens !!! j'ai ça comme page 8O J'ai utilisé ta page de ATOMIC convertie en UNICODE
Server listening on port 6834
Client IP 127.0.0.1 load index.html
Client IP 127.0.0.1 load favicon.ico
Client IP 163.95.19.52 load index.html
Client IP 163.95.19.52 load favicon.ico

Re: Simple Web Server

Publié : lun. 13/févr./2017 19:24
par falsam
Je crois avoir répondu dans le sujet atomic qu'il fallait créer les pages en UTF8 seul

Je vais quand même tester ces pages.

Re: Simple Web Server

Publié : mar. 14/févr./2017 10:11
par Kwai chang caine
Oui tu as raison, je suis allé relire, j'avais codé en UNICODE et ça avait marché pour ATOMIC :oops:
Pas besoin, je suis passé en UTF8 et ça marche nickel, merci FALSAM 8)

Juste un petit bémol ..j'ai une balise </HTML> qui traine 8O
Atomic Web Server (Unicode)

Ceci est la prémiere page de votre site web. / This is the first page of your website.
</html
Une question me trotte....crois tu que ça serait compliqué de rajouter PHP ?

Re: Simple Web Server

Publié : mar. 14/févr./2017 10:42
par djes
Kwai chang caine a écrit :Une question me trotte....crois tu que ça serait compliqué de rajouter PHP ?
8O :mrgreen:
Y'a que KCC pour sortir un truc pareil, avec une telle ingénuité !
Bon courage falsam ! :lol:

Re: Simple Web Server

Publié : mar. 14/févr./2017 10:49
par GallyHC
Bonjour,

Une toute petite modification au niveau de :

Code : Tout sélectionner

  ;Definition du content-type / Setup content-type
  ;Ref : https://fr.wikipedia.org/wiki/Type_MIME
  Select GetExtensionPart(RequestedFileExtension)
    Case ".css" : ContentType = "text/css"
    Case ".js"  : ContentType = "application/javascript" 
    Case ".gif" : ContentType = "image/gif"
    Case ".jpg" : ContentType = "image/jpeg"
    Case ".png" : ContentType = "image/png"
    Case ".txt" : ContentType = "text/plain"
    Case ".zip" : ContentType = "application/zip"
    Case ".pdf" : ContentType = "application/pdf"
      
    Default     
      ContentType = "text/html" 
  EndSelect
Perso je mettrais :

Code : Tout sélectionner

Default     
      ContentType = "application/octet-stream" 
  EndSelect
Car tu n'est pas sur que ce soit un fichier Texte. Ton lien donne pour cela :
application/octet-stream : flux de données arbitraire. Considéré comme le format « par défaut » dans plusieurs OS, souvent utilisé pour identifier des fichiers exécutables, ou de type inconnu, ou des fichiers qui doivent être téléchargés grâce à des protocoles qui ne fournissent pas de champ « content disposition » dans leur en-tête. La RFC 2046 [archive] le décrit comme un recours pour les sous-types et les types non reconnus.
Cordialement,
GallyHC

Re: Simple Web Server

Publié : mar. 14/févr./2017 11:11
par falsam
@Gally: Oui tu as raison. Code modifié.
Djes a écrit :Y'a que KCC pour sortir un truc pareil, avec une telle ingénuité !
+1

@KCC: Et non. Pas de PHP. L'objectif de ce code est d'afficher des pages uniquement statics. Par contre tu peux utiliser JavaScript au dans tes pages HTML

Si tu souhaites gérer la dynamique des pages, alors il faut utiliser la version ++ de Simple Web Server.

:arrow: http://www.purebasic.fr/french/viewtopi ... =6&t=16490

Re: Simple Web Server

Publié : mar. 14/févr./2017 11:59
par Kwai chang caine
Merci de ton explication Falsam
J'ai encore du mal à comprendre la différence entre les deux
C'est peut être justement que l'un est statique et l'autre non :oops:
djes a écrit :
Kwai chang caine a écrit :Une question me trotte....crois tu que ça serait compliqué de rajouter PHP ?
8O :mrgreen:
Y'a que KCC pour sortir un truc pareil, avec une telle ingénuité !
Bon courage falsam ! :lol:
Quel "mouqueur" ce DJES :lol:

Bon alors j'ai encore pas tout compris, ou je me suis mal exprimé. ..ou les deux :mrgreen:
Je pensais à faire comme APACHE, car c'est bien de lui qu'on veut se passer ??
Récupérer la page et lorsque l'on détecte du php avec les balises <? Php> et bien on l'envoi a l'exe PHP pour qu'il fasse le job.

Car évidemment ça serait un boulot de guedin de tout recréér les centaines de fonctions PHP, et réinventer la roue.
En plus ce serait ridicule car on ne pourrait pas changer la syntaxe sous peine de se couper du reste du monde..

Re: Simple Web Server

Publié : mar. 14/févr./2017 12:11
par djes
Kwai chang caine a écrit :
djes a écrit :
Kwai chang caine a écrit :Une question me trotte....crois tu que ça serait compliqué de rajouter PHP ?
8O :mrgreen:
Y'a que KCC pour sortir un truc pareil, avec une telle ingénuité !
Bon courage falsam ! :lol:
Quel "mouqueur" ce DJES :lol:

Bon alors j'ai encore pas tout compris, ou je me suis mal exprimé. ..ou les deux :mrgreen:
Je pensais à faire comme APACHE, car c'est bien de lui qu'on veut se passer ??
Récupérer la page et lorsque l'on détecte du php avec les balises <? Php> et bien on l'envoi a l'exe PHP pour qu'il fasse le job.

Car évidemment ça serait un boulot de guedin de tout recréér les centaines de fonctions PHP, et réinventer la roue.
En plus ce serait ridicule car on ne pourrait pas changer la syntaxe sous peine de se couper du reste du monde..
Bien sûr que c'est faisable, mais justement, falsam met en place des balises pour faire comme php mais en PB, ce n'est pas pour implémenter un truc qui existe déjà, surtout que c'est hyper lourdingue ! Et vu que c'est de l'Open source, rien n'empêche quiconque de le faire, il donne tous les outils pour.

Re: Simple Web Server

Publié : mar. 14/févr./2017 12:21
par Kwai chang caine
Aaaaah ok !!!
J'ai cru que j'étais à côté de la plaque :oops:
Perso je suis pas fan de php, mais mettre en place nos propres balise ça va pas rendre les pages de Falsam illisibles par les serveurs "normaux"...
C'est là que je comprends pas tout :oops:

Re: Simple Web Server

Publié : mar. 14/févr./2017 12:29
par falsam
mettre en place nos propres balise ça va pas rendre les pages de Falsam illisibles par les serveurs "normaux"...
Que tu es Beta ^^ héhé

Les pages comportant ces balises sont uniquement interprétées par le serveur codé avec PureBasic.

:!: Rappel : Ce code ne fait qu'affiché des page statics ne comportant pas ce type de balise :wink:

Re: Simple Web Server

Publié : mar. 14/févr./2017 13:26
par falsam
Kwai chang caine a écrit :Juste un petit bémol ..j'ai une balise </HTML> qui traine
Et bien pas chez moi avec le meme test.

Tu peux cliquer sur cette exemple http://109.13.115.206:6834/index.html qui ne sera plus visible à minuit.

Re: Simple Web Server

Publié : mar. 14/févr./2017 15:18
par Ar-S
Si tu regarde ton code source (de la page web), ta balise de fin n'est pas fermée.

Code : Tout sélectionner

</html

Re: Simple Web Server

Publié : mar. 14/févr./2017 15:39
par falsam
Alors là ..... pas de réponse !!!

Si je débogue la variable HTMLContent juste avant l'instruction SendNetworkString() la page HTML est complète avec la balise <html> fermée.

Le rendu de la page est correcte mais pas le code source final. C'est perturbant.

Re: Simple Web Server

Publié : mar. 14/févr./2017 17:01
par falsam
Rhoo je viens de voir une grosse lacune dans ce code !!!!!

/me cherche une pelle pour s'enfoncer le plus possible dans le sol :oops: