Search code examples
pharo

Try to use ZnServer for GET and POST requests


Sorry for asking a possibly dumb question, but after reading documentation, looking at examples, etc., I still didn't find a solution for what I'm trying to do.

I used Pythons web server as a part of a larger project. It serves static files via do_GET method and can handle POST requests (sent by the client using XMLHTTPRequest) via do_POST method. Everything is working well.

What I'm trying to do is an implementation of the web server in Pharo. I think that ZnServer (part of Pharo 2.0) is the way to go. It must be able to serve static files and handle POST requests.

Python code for a very simple http server example

# httpd_test.py

# Imports
import os
import sys
import cgi
import json
from   BaseHTTPServer import BaseHTTPRequestHandler
from   BaseHTTPServer import HTTPServer

# HTTP Request Handler Class
class RequestHandler(BaseHTTPRequestHandler):

   # Process GET requests
   def do_GET(self):

      print(self.path)

      # Send response
      tex = 'GET: ' + self.path
      self.send_response(200)
      self.send_header('Content-type','text/plain')
      self.send_header('Content-length',str(len(tex)))
      self.end_headers()
      self.wfile.write(tex)
      self.wfile.flush()

   # Process POST requests
   def do_POST(self):

      # Read CGI data
      CgiData = cgi.FieldStorage(fp      = self.rfile,
                                 headers = self.headers,
                                 environ = {'REQUEST_METHOD':'POST',
                                            'CONTENT_TYPE':self.headers['Content-Type']})

      # Invoke action
      if self.path == '/handler':
         print(repr(CgiData))
      else:
         print('Unknown POST handler.')
         print(repr(CgiData))

      # Send response
      self.send_response(200)
      tex = repr(CgiData)
      self.send_header('Content-type','text/plain')
      self.send_header('Content-length',str(len(tex)))
      self.end_headers()
      self.wfile.write(tex)
      self.wfile.flush()

# Start Server
if __name__  == '__main__':
    server = HTTPServer(('127.0.0.1',8080),RequestHandler)
    server.serve_forever()

What I have tried in Pharo (but with no luck)

start
    "Start ZnServer default"

    | staticFileServerDelegate |

    ZnServer startDefaultOn: 8080.

    (ZnServer default) logToTranscript.

    (ZnServer default) authenticator: (ZnBasicAuthenticator username: 'foo' password: 'bar').

    staticFileServerDelegate := ZnStaticFileServerDelegate new.
    staticFileServerDelegate    prefixFromString: 'zn';
                                            directory: 'C:\Temp'.

"   (ZnServer default) delegate prefixMap
        at: 'zn'
        put:    [ :request | staticFileServerDelegate handleRequest: request ];
        at:  '/'
        put:    [ :request | ZnResponse redirect: 'C:\Temp' ]."

    (ZnServer default) delegate prefixMap
        at:  '/'
        put:    [ :request | Transcript cr; show:'1 '; show: request; cr. ];
        at: 'handler'
        put: [ :request | Transcript cr; show:'3 '; show: request; cr. ].

"start" is a class method of an own class with no base class.

I'm a newbie to Pharo, so it's possible that I'm on the wrong track. I hope, the description is clear enough, so one can see what I want to do. Any help on this would be highly appreciated.

Thanks in advance.


Solution

  • As a default server, this should work:

    (ZnServer startDefaultOn: 8080) 
        onRequestRespond: [ :request | 
            ZnResponse ok: (ZnEntity text: 'Hiya!') ].
    

    Then you can manage the documents answered on ZnResponse. But why don't you use something more powerful like Seaside? http://seaside.st