我正在为Python编写一个Web框架,其目标是尽可能"小"(目前在100行代码下).您可以在github上看到当前代码
基本上它被编写为尽可能简单易用.像网站一样的"Hello World"示例:
from pyerweb import GET, runner @GET("/") def index(): return "This 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"
基本上你有一个返回HTML的函数,而GET装饰器将它映射到一个URL.
当runner()
被调用时,每个装饰功能检查,如果该URL的正则表达式的请求URL匹配,运行该功能,并将输出发送到浏览器.
现在,问题 - 输出标题.目前为了开发我只是在runner()
通话之前放了一行print Content-type:text/html\n
- 这显然有点限制..
我的第一个想法是让函数返回一个dict,比如...
@GET("/") def index(): return { "html": "...", "headers": {"Location":"http://google.com"} }
我真的不喜欢这个 - 必须返回一个带有特定命名键的dict并不像返回一个字符串那么好.
我可以检查返回的数据是否是一个dict,如果是的话returned_data['html']
用作输出,如果它是一个字符串,就没有自定义标题要发送......但是这意味着从没有标题开始(这将是一个巨大的情况)大部分时间),以头,你必须改变返回功能从return my_html
到return {'html':my_html}
这是不是很优雅..要么
写完之后,我发现了"Sinatra" - 一个类似使用的Ruby库,并研究了它如何处理标题:
get "/" do content_type 'text/css', :charset => 'utf-8' end
这似乎在Python中足够好:
@GET("/") def index(): header("location", "http://google.com")
为了实现这一点,我正在考虑改变函数的执行方式 - 而不是简单地使用返回值,我将改为sys.stdout
StringIO,所以你可以做..
def index(): print "" print "Something " print "..." print "
..而不必担心将一堆字符串连接在一起.这样做的结果是我可以有一个单独的标题流,所以上面的header()
函数会写到这个..类似于:
def header(name, value): pyerweb.header_stream.write("%s: %s" % (name, value))
基本上,问题是,您将如何从此Web框架输出标头(主要是在使用方面,但在较小程度上实现)?
查看PEP 333,了解非常轻量级Web服务器的出色设计模式.如果您的服务器具有此确切的API,则可以在许多其他产品的许多上下文中重复使用它.
PEP 333(WSGI)建议您不直接返回页面,但是您将HTML页面提供给"start_response"可调用对象,该对象使用正确的标头将HTML包装在正确的HTTP响应中.