How to create a Webserver that supports CXP pages

Xbase++ 2.0 Build 554 or later
Post Reply
Message
Author
User avatar
rdonnay
Site Admin
Posts: 4729
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

How to create a Webserver that supports CXP pages

#1 Post by rdonnay »

Below is the source code for a Web server that was created in Xbase++ 2.0 using HttpEndPoint().

There are now 2 Web servers running on bb.donnay-software.com that support CXP pages:

1. Apache Web Server on Port 80 (configured for fastCGI)
2. CxpHttpServer.Exe on Port 81 (an Xbase++ application)

Click below to see the CXPINFO.CXP pages side by side in your web browser.
This proves that CXP pages can be run without the need for IIS or Apache.

http://bb.donnay-software.com/cxpcompare.htm

This is the content of CXPcompare.htm:

Code: Select all

<html>
<frameset cols="*,*" frameborder=no border=0>
  <frame name="cxpinfo1" src="http://bb.donnay-software.com/cxpinfo.cxp" scrolling="auto">
  <frame name="cxpinfo2" src="http://bb.donnay-software.com:81/cxpinfo.cxp" scrolling="auto">
</frameset>
</html>
This is the source code for CXPINFO.CXP

Code: Select all

<!DOCTYPE html>
<%#Code locality="page-global"%>
<%
 CLASS Table
   PROTECTED:
   VAR Data
   VAR CSS
   VAR Columns
   VAR Title

   EXPORTED:
   METHOD Init()
   METHOD AddRow()
   METHOD Render()
   METHOD AddSeparator()
 ENDCLASS

 METHOD Table:Init(cT,nC,cC)
   ::Title   := cT
   ::Columns := nC
   ::CSS     := cC
   ::Data    := {}
 RETURN

 METHOD Table:AddRow(cT1,cT2)
   LOCAL n
   aData := Array( ::Columns )
   FOR n:=1 TO ::Columns
     aData[n] := PValue(n)
   NEXT n
   AAdd( ::Data, aData )
 RETURN

 /*
  * Nothing special but this is how it is
  */
 METHOD Table:Render()
   LOCAL cText,cToday
   LOCAL n,m
   cText := "<table class="+::CSS+'>'+Chr(13)+Chr(10)
   IF(!Empty(::Title))
      cText += '<thead><tr><td colspan="'+StrZero(::Columns,3)+'">'+::Title
      cText += "</td></tr></thead>"+Chr(13)+Chr(10)
   ENDIF
   FOR n:=1 TO Len(::Data)
     IF(ValType(::Data[n])=="C")
       cText += '<tr class="metro-red"><td colspan="'+StrZero(::Columns,3)+'">'+::Data[n]+'</td></tr>'+Chr(13)+Chr(10)
     ELSE
       cText += '<tr class="metro-blue">'+Chr(13)+Chr(10)
       FOR m:=1 TO Len(::Data[n])
         cText += "<td>"+Var2Char(::Data[n][m])+"</td>"+Chr(13)+Chr(10)
       NEXT m
       cText += "</tr>"+Chr(13)+Chr(10)
     ENDIF
   NEXT n
   cText += "</table>"+Chr(13)+Chr(10)
 RETURN(cTexT)

 METHOD Table:AddSeparator(cD)
   AAdd( ::Data, cD )
 RETURN
%>

<html>
<style>
body{
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}

table.clearblue {
  border-collapse:collapse;
  background-color: #3ba2e9; /* alaska metro-style-light blue */

  /* remove these two border defs to get rid of the table border */
  border-left:  15px solid #27348B; /* deep dark AlaskaBlue */
  border-top:    5px solid #27348B;
  width: 600px;
}

table.clearblue td {
  padding: 2px 10px 2px 5px;
  border-top:   0px solid black;
  border-bottom:1px solid #27348B;
  border-left:  0px solid black;
  border-right: 0px solid black;
  font-size:    10pt;
}

table.clearblue thead {
   background-color: #27348B;
   color:  #F3F3F1;
   margin-left:-5px;
   padding-left:10px;
   height: 40px;
}

tr.metro-blue{
  background-color: #3ba2e9;
}

tr.metro-red{
  background-color: #cd6552;
}
</style>
<title>Compiled Xbase++ Pages Installation Report</title>
<div>
<%
 SET DATE TO AMERICAN

 cTitle := [<font style="font-weight:bold;font-size:18pt;"><CXP/>&nbsp;InfoPage</font>&nbsp;<font style="font-size:8pt;">(created ::Today)</font>]
 cTitle := StrTran(cTitle,"::Today",DToC(Date()))

 oTab := Table():New(cTitle,2,"clearblue")
 oTab:AddSeparator("Platform:")
 oTab:AddRow( "Http Server", ::HttpRequest:GetVariable("SERVER_SOFTWARE") )
 oTab:AddRow( "Operating System", OS() )
 oTab:AddRow( "Patches Installed", OS(6) )
 oTab:AddRow( "Processors",GetEnv("NUMBER_OF_PROCESSORS"))

 oTab:AddSeparator("Compiled Xbase++ Pages:")
 oTab:AddRow( "Runtime" , Version(1)+"."+Version(2)+" Build " + Version(3) )
 oTab:AddRow( "ExtendedTypes", Var2LChar( IsFunction( "datetime" )))
 oTab:AddRow( "Server API", ::HttpRequest:GetVariable("GATEWAY_INTERFACE") )
 oTab:AddRow( "Installation", Lower( CurDrive()+":\"+CurDir() ) )

 oTab:AddSeparator("CxpPage Env:")
 oTab:AddRow("Page",SELF:File)
 oTab:AddRow("Path",SELF:Path)
 oTab:AddRow("PhysicalPath",SELF:PhysicalPath)
 oTab:AddRow("Form Data",Var2char(SELF:HttpRequest:Form:Collection ))
 oTab:AddRow("Session Data",Var2char(SELF:Session:Collection ))
 oTab:AddRow("PageConfig"  ,CoalesceEmpty(SELF:ConfigFile,"(No local page config found)"))
 oTab:AddRow("Host",SELF:Host:ClassName())
 oTab:AddRow("Application",SELF:Application:ClassName())
 oTab:AddRow("SessionProvider",SELF:Session:ClassName())
 oTab:AddRow("CachePolicy",IIF(ValType(SELF:CachePolicy)=="O",SELF:CachePolicy:ClassName(),"(No cache provider)"))

 oTab:AddSeparator("CxpWorker Env.:")
 oTab:AddRow("Path"        , Var2Char( GetEnv("PATH")))
 oTab:AddRow("Comspec"     , Var2Char( GetEnv("COMSPEC")))
 oTab:AddRow("SystemRoot"  , Var2Char( GetEnv("WINDIR")))
 oTab:AddRow("Current"     , Lower( CurDrive()+":\"+CurDir() ) )
 oTab:AddRow("Identity"    , Var2Char( GetEnv("USERNAME") )  )
 oTab:AddRow("User Profile"    , Var2Char( GetEnv("USERPROFILE") )  )
 oTab:AddRow("Temp Location"    , Var2Char( GetEnv("TEMP") )  )
 oTab:AddRow("Application Data"    , Var2Char( GetEnv("APPDATA") )  )

 oTab:AddSeparator("Http Server Env.:")
 oTab:AddRow("Server Software"  , Var2Char( ::HttpRequest:GetVariable("SERVER_SOFTWARE")))
 oTab:AddRow("Server Name"      , Var2Char( ::HttpRequest:GetVariable("SERVER_NAME")))
 oTab:AddRow("Server Address"   , Var2Char( ::HttpRequest:GetVariable("SERVER_ADDR")))
 oTab:AddRow("Server Port"      , Var2Char( ::HttpRequest:GetVariable("SERVER_PORT")))
 oTab:AddRow("Document Root"    , Var2Char( ::HttpRequest:GetVariable("DOCUMENT_ROOT")))
 oTab:AddRow("Server Admin"  , Var2Char( ::HttpRequest:GetVariable("SERVER_ADMIN")))
 oTab:AddRow("Script Filename"  , Var2Char( ::HttpRequest:GetVariable("SCRIPT_FILENAME")))
 oTab:AddRow("Server Protocol"  , Var2Char( ::HttpRequest:GetVariable("SERVER_PROTOCOL")))
 oTab:AddRow("Request Method"   , Var2Char( ::HttpRequest:GetVariable("REQUEST_METHOD")))
 oTab:AddRow("Query String"     , Var2Char( ::HttpRequest:GetVariable("QUERY_STRING")))
 oTab:AddRow("Request URI"      , Var2Char( ::HttpRequest:GetVariable("REQUEST_URI")))
 oTab:AddRow("Script Name"      , Var2Char( ::HttpRequest:GetVariable("SCRIPT_NAME")))

 oTab:AddSeparator("Http Request Env:")
 oTab:AddRow("Accept"           , Var2Char( ::HttpRequest:GetVariable("HTTP_ACCEPT")))
 oTab:AddRow("Referer"          , Var2Char( ::HttpRequest:GetVariable("HTTP_REFERER")))
 oTab:AddRow("Accept Languages" , Var2Char( ::HttpRequest:GetVariable("HTTP_ACCEPT_LANGUAGE")))
 oTab:AddRow("User Agent"       , Var2Char( ::HttpRequest:GetVariable("HTTP_USER_AGENT")))
 oTab:AddRow("Remote Address"   , Var2Char( ::HttpRequest:GetVariable("REMOTE_ADDR")))
 oTab:AddRow("Remote Port"      , Var2Char( ::HttpRequest:GetVariable("REMOTE_PORT")))
 oTab:AddRow("Accept Encoding"  , Var2Char( ::HttpRequest:GetVariable("HTTP_ACCEPT_ENCODING")))
 oTab:AddRow("Host"             , Var2Char( ::HttpRequest:GetVariable("HTTP_HOST")))
 oTab:AddRow("Connection"       , Var2Char( ::HttpRequest:GetVariable("HTTP_CONNECTION")))
 oTab:AddRow("Cookies:", Var2Char( ::HttpRequest:Cookies:Collection ) )
 oTab:AddRow("Headers:", Var2Char( ::HttpRequest:Headers ) )

 ? oTab:Render()

%>
</div>
</html>

This is the source code for CXPHttpServer.Exe

Code: Select all

#include "inkey.ch"
#include "web.ch"
#include "assert.ch"
#INCLUDE "dcdialog.CH"

#define PORT 81

FUNCTION Main( cHost )

LOCAL cPort, oCxpHttpEndpoint, cHtml
LOCAL GetList[0], GetOptions, aUrl, i, lStarted := .f.

DEFAULT cHost := "http://" + GetEnv('Computername')
cPort := AllTrim(Str(PORT))

oCxpHttpEndpoint := CxpHttpEndpoint():new( PORT )

@ 0,0 DCSAY "CxpHttpEndpoint sample." FONT '12.Arial Bold'

@ 2,0 DCPUSHBUTTON CAPTION {||IIF(lStarted,'STOP','START') + ' Cxp/Http Server'} SIZE 30,1.5 ;
      FONT '10.Arial Bold' ;
      ACTION {||lStarted := !lStarted, ;
                IIF(lStarted,oCxpHttpEndPoint:start(),oCxpHttpEndPoint:stop()), ;
                DC_GetRefresh(GetList)}

DCGETOPTIONS SAYWIDTH 0

DCREAD GUI FIT ADDBUTTONS TITLE 'Testing CxpHttpEndPoint' ;
  OPTIONS GetOptions

IF lStarted
  oCxpHttpEndpoint:stop()
ENDIF

RETURN nil

* -----------

PROC appsys ; RETURN


/// <summary>
/// We override DefaultProcessor so we can add our
/// CXP and HTMLFile processors which we need for
/// web debuging.
/// </summary>
CLASS CxpHttpEndPoint FROM HttpEndPoint
  EXPORTED:
  METHOD DefaultProcessors()
  METHOD DefaultConfig()
ENDCLASS

METHOD CxpHttpEndPoint:DefaultProcessors()
  LOCAL aRet := SUPER:DefaultProcessors()
  AAdd( aRet , "CxpProcessor" )
  AAdd( aRet , "HtmlFileProcessor" )
RETURN(aRet)

METHOD CxpHttpEndPoint:DefaultConfig(cToken)
  LOCAL oDO := DataObject():New()

  IF( !("CDXDBE" $ dbelist()))
    DbeLoad("CDXDBE")
  ENDIF
  IF( !("FOXDBE" $ dbelist()))
    DbeLoad("FOXDBE")
  ENDIF
  IF( !("FOXCDX" $ dbelist()))
    DbeBuild("FOXCDX","FOXDBE","CDXDBE")
  ENDIF

  cToken := Lower(AllTrim(cToken))

  IF(cToken=="session")
    oDO:Provider := "CxpCookieSessionManager"
    oDO:Timeout  := 15
  ELSEIF(cToken=="storage")
   oDO:Provider := "AppStorageManager"
   oDO:Store    := "cxp-data\application-storage.dbf"
  ENDIF
RETURN(oDO)
The eXpress train is coming - and it has more cars.

Cliff Wiernik
Posts: 605
Joined: Thu Jan 28, 2010 9:11 pm
Location: Steven Point, Wisconsin USA
Contact:

Re: How to create a Webserver that supports CXP pages

#2 Post by Cliff Wiernik »

So, what needs to be done to make the sample web server support SSL. That would be without a separate certificate, but just normal https:// Or is that also what is not yet documented. I know at the sessions and newsgroup they were commenting about the server side not yet supporting it.

skiman
Posts: 1185
Joined: Thu Jan 28, 2010 1:22 am
Location: Sijsele, Belgium
Contact:

Re: How to create a Webserver that supports CXP pages

#3 Post by skiman »

Hi Roger,

It looks as the page on http://bb.donnay-software.com:81/cxpinfo.cxp doesn't respond at this moment.

It would be super to use an Xbase++ application as server instead of IIS or Apache.
Best regards,

Chris.
www.aboservice.be

User avatar
rdonnay
Site Admin
Posts: 4729
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: How to create a Webserver that supports CXP pages

#4 Post by rdonnay »

It looks as the page on http://bb.donnay-software.com:81/cxpinfo.cxp doesn't respond at this moment.
Sorry -

I have to keep shutting it down to deploy changes to eXpress++ DLLS.
I have been working a lot on eXpress++ 2.0.

I restarted it. Try again.

http://bb.donnay-software.com:81/cxpinfo.cxp
The eXpress train is coming - and it has more cars.

skiman
Posts: 1185
Joined: Thu Jan 28, 2010 1:22 am
Location: Sijsele, Belgium
Contact:

Re: How to create a Webserver that supports CXP pages

#5 Post by skiman »

Yes, it works now.
Best regards,

Chris.
www.aboservice.be

Post Reply