Web Server example

I have been testing the webserver example which appears to listen and serve content, however .html pages are all served as plain text:

The following code is what reads the index.html file and outputs it to the browser, however it is not rendered and is all sent as plain text:

    // Open the file up for reading only
    bs = BinaryStream.Open(f, False)
    // Write out the contents of the file to the remote side
    Self.Write( bs.Read( bs.Length ) )
    // Close the file
    bs.close

How do I get it to be rendered as html ??

Take a look at this thread from the old RB forums.

There are also a couple of HTTP servers written in Xojo that are much more complete than the example, there’s mine and there’s Brandon Skrtich’s, and possibly others.

Andrew;

That’s a huge help, thanks, I’ve looked at your code and that would be great if I needed a public server, where I needed it to support sessions etc and be more secure, but what I am looking for at the moment is a private very very light web server, that will probably be used accessed by 1 or maximum 2 users within an small business or home intranet.

The link to the old forum thread was helpful, the pages are now being rendered and style sheets and js are working, only thing that is not loading is the icons, but I guess that is something to do with the mime types ?

This is basically a jquery mobile site, with ajax calls to the local webserver, where I will parse the url parameters to perform sql select and updates / inserts to retrieve and write data to a sqlite databse.

Many Thanks again.

The icons not rendering is very likely a content-type issue. Make sure you’re sending the right type (e.g. “image/jpeg”, “image/png”, etc.)

Hmmm. I have added a file extension lookup to set the mime type correctly, that appears to be working OK.

Firefox and Ipad both render the pages correctly, however Chrome and OSX Safari are not loading / parsing the stylesheets at all, and I’m not really sure why.

I guess that Firefox / Ipad are more forgiving in terms of what is being outputted, but are there any other headers other than the content type that are essential and must be sent ??

Also, Do I need to set the “charset=UTF-8” for all content types ?

What content-type are you sending for CSS files? It should be “text/css”.

charset=utf-8 may be sent with any “text” type. e.g. “text/html”, “text/plain”, “text/css”. It’s optional.

Yes, its sending the correct type text/css

Sometimes chrome refuses to load a css file and sometimes it wont load a js file.

What other headers besides Content-Type are you using? You may need to append (e.g.) Content-Length and Content-Encoding headers. I’ve found that different browsers react differently to the absence of certain common response headers.

Currently, I am sending the following headers:

Array
(
[0] => HTTP/1.1 200 OK
[Content-Type] => text/html
[Content-Length] => 706
[Connection] => close
)

But I ran Brandon Skrtich’s code and it has the same problem, so I no longer think it’s related to the headers.

It looks like Chrome may not like css / js files on high ports ( 8088 ), but mac won’t allow access to ports under 1024 unless ran as root, so I need to try and run this as a system launch daemon so it runs as root.

Just a shot in the dark, but try specifying “HTTP 1.0” rather than “HTTP 1.1”. I’ve found that 1.0 can be more forgiving, depending on the client.

Thanks Andrew, I tried sending HTTP 1.0, no difference I’m afraid, and I’ve spent sooooo many hours on this, just cannot resolve it, the application seems to be completely erratic, sometimes it will load and show pages 100% correct, sometimes partially, I am coming to the conclusion that this cannot be done (or more accurately I cannot do this !)

if I keep reloading the same page, sometimes it will display correctly, sometimes with images missing, sometimes with no css applied, sometimes without js pages loaded.

Andrew I tried running your code and it fails to compile with the following errors (osx 10.8.3):

This item does not exist:
StructureInfo = CFUUIDCreateString(Nil, pUUID)

You must use the value returned by this function:
CFRelease(pUUID)

I am really looking for something very simple that I can drop into my console application to serve a very very low volume, one or 2 users maximum, I can’t believe how difficult this is.

I have already completed the html / js / ajax etc, I just can’t get xojo to serve it reliably :frowning:

I don’t have OS X to test on, but that error is in the only OS X-specific part of the code :\

Andrew;

Thanks, that’s very generous of you, I have tested very quickly in the office using the following settings, but it was unable to find the page. later in the afternoon I will test more thouroughly and also send you a link so you can also see the output:

  Dim SomeFolder As FolderItem = GetFolderItem("/volumes/data1/users/pac/web/",1)
  msgbox SomeFolder.NativePath
  
  Dim QnD As New QnDHTTPd(SomeFolder)
  Qnd.Authenticate = false
  QnD.Page = SomeFolder
  QnD.Port = 8800
  QnD.Listen()

You probably will need to tweak the “FindFile” method to work with Mac-style paths.

Andrew, my apologies, I just re-wrote this reply after more testing, it’s now working.

However it is still erratic, sometimes displaying correctly and sometimes not loading images, stylesheets or js script.

This appears to be the same behavior with SAFARI and CHROME Browsers and to a lesser extent with FIREFOX.

Not sure if this link is working: Test Page so you can see for yourself.

Sub Open()
  Dim SomeFolder As FolderItem = GetFolderItem("/Library/WebServer/Documents/cs",0)
 
  Dim QnD As New QnDHTTPd(SomeFolder)
  Qnd.KeepListening = true
  Qnd.Authenticate = false
  Qnd.AllowDirectoryIndexPages = true
  QnD.Page = SomeFolder
  QnD.Port = 8800
  QnD.Listen()
End Sub
Private Function FindItem(Path As String) As FolderItem
  Dim s As String
  Path = NthField(Path, "?", 1)
  
  If Not Page.Directory And "/" + Page.Name = path Then
    Me.Log("Request found at page/root.", Severity_Debug)
    Return Page
  End If
  
  s = page.name + path
  Me.Log("Found: " +s, Severity_Debug)
  Return GetTrueFolderItem(s,1)
  
End Function

Ahh, it seems to be erroring as well, not sure what the cause is:

Jun 28 20:06:56 pacMacPro.local My Application.debug[16529]: My Application.debug: (Fri, 28 Jun 2013 12:06:56 GMT) 
	Socket Error: 102

So if the link does work, it may have alread shut itself down.

Error 102 is a disconnection. Since QnD is a single TCPSocket it can only handle one request per socket. You need to either tell the socket to re-Listen after every request (set QnD.KeepListening=True) or use it in a ServerSocket. Using a ServerSocket is best, especially if more than one user is expected simultaneously.

e.g. add a serversocket to a window and put this in its AddSocket event:

Event AddSocket() As TCPSocket
   Dim QnD As New QnDHTTPd(DocumentRootFolderItem)
   Return QnD
Event

Thanks Andrew;

Qnd.KeepListening = true is already set (see code in post above)

I added the following:

Sub Error()
  Me.Log("Socket Error: " + Str(Me.LastErrorCode), Severity_Caution)
  if me.LastErrorCode = 102 then
    me.Listen
  else
    Me.Close()
    RaiseEvent Error()
  end if
End Sub

But I am getting the same problem as I was facing with the sample http server code that I was working on previously, i.e the linked files, images and stylesheets etc don’t always load:

I have the same web folder being served both by apache and the Qnd Xojo Server:

Xojo Server

Apache Server

The apache version appears to be stable and loads every time, the xojo server fails to load with each refresh.

KeepListening=True is a hack I was using before the ServerSocket became available to all license levels. Use the serversocket unless you have a good reason not to.

FWIW both seem to work for me, though the Xojo server feels slower.