Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 416 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Emitting headers from a tiny Python web-framework

#1
I am writing a web-framework for Python, of which the goal is to be as "small" as possible (currently under 100 lines of code).. You can see the current code [on github](

[To see links please register here]

)

Basically it's written to be as simple to use as possible. An example "Hello World" like site:

from pyerweb import GET, runner

@GET("/")
def index():
return "<strong>This</strong> would be the output HTML for the URL / "

@GET("/view/([0-9]+?)$")
def view_something(id):
return "Viewing id %s" % (id) # URL /view/123 would output "Viewing id 123"

runner(url = "/", # url would be from a web server, in actual use
output_helper = "html_tidy" # run returned HTML though "HTML tidy"

Basically you have a function that returns HTML, and the GET decorator maps this to a URL.

When `runner()` is called, each decorated function is checked, if the URL regex matches the request URL, the function is run, and the output is sent to the browser.

Now, the problem - outputting headers. Currently for development I've just put a line before the `runner()` call which does `print Content-type:text/html\n` - this is obviously a bit limiting..

My first ideas was to have the functions return a dict, something like..

@GET("/")
def index():
return {
"html": "<html><body>...</body></html>",
"headers": {"Location":"http://google.com"}
}

I really don't like this - having to return a dict with a specifically named key isn't nearly as nice as just returning a string..

I could check if the returned data is a dict, if so use `returned_data['html']` as the output, if it's a string, there is no custom headers to be sent... but this means to go from no headers (which would be the case a huge majority of the time) to headers, you'd have to change the return function from `return my_html` to `return {'html':my_html}` which isn't very elegant either..

After writing this, I discovered "Sinatra" - a similar-in-use Ruby library, and looked at how it dealt with headers:

get "/" do
content_type 'text/css', :charset => 'utf-8'
end


This seems like it could be nice enough in Python:

@GET("/")
def index():
header("location", "http://google.com")

To implement this, I was considering changing how the functions are executed - instead of simply using the return value, I would change `sys.stdout` to a StringIO, so you could do..

def index():
print "<html>"
print "<head><title>Something</title></head>"
print "<body>...</body>"
print "</html>

..without having to worry about concatenating a bunch of strings together. The upshot of this is I could have a separate stream for headers, so the above `header()` function would write to this.. Something like:

def header(name, value):
pyerweb.header_stream.write("%s: %s" % (name, value))


Basically, the question is, how would you output headers from this web-framework (mostly in terms of *use*, but to a lesser extent implementation)?
Reply

#2
You should reconsider the notion of returning [HTML][1] - headers are part of [HTTP][2].
If you build your framework around an HTTP stream, the headers are simply lines that precede the HTML payload.

A headers example from the above link:

HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Etag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8

For a Python example, see the implementaion of [`BaseHTTPRequestHandler.send_header(keyword, value`)][3].


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply

#3
you could use that idea of returning a dict or a string, but add a new decorator, so the 'evolution' for a user would be:

simple html:

@GET("/")
def index():
return "<html><body>...</body></html>"

with constant headers (one @HEADER for each one, or a dict with all of them):

@GET("/")
@HEADER("Location","http://google.com")
def index():
return "<html><body>...</body></html>"

with complex, maybe calculated headers:

@GET("/")
def index():
return {
"html": "<html><body>...</body></html>",
"headers": {"Location":"http://google.com"}
}

the @HEADER() decorator would simply change the returned value, so the 'framework' code would stay simple.
Reply

#4
Look at [PEP 333][1] for an excellent design pattern for a very lightweight web server. If your server has this exact API, you can reuse it in a lot of context with a lot of other products.

PEP 333 (WSGI) suggests that you don't directly return the page, but you provide the HTML page to a "start_response" callable object, which wraps your HTML in the proper HTTP response, with the proper headers.


[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through