How to create a Webserver that supports CXP pages
Posted: Sat Nov 08, 2014 11:26 am
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:
This is the source code for CXPINFO.CXP
This is the source code for CXPHttpServer.Exe
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>
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/> InfoPage</font> <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>
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)