Я пишу веб-фреймворк для Python, цель которого состоит в том, чтобы быть как можно более «маленьким» (в настоящее время менее 100 строк кода). Вы можете увидеть текущий код на github
По сути, это написано, чтобы быть максимально простым в использовании. Пример "Hello World", как сайт:
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"
По сути, у вас есть функция, которая возвращает HTML, и декоратор GET отображает это в URL.
Когда вызывается runner()
, проверяется каждая оформленная функция, если регулярное выражение URL совпадает с URL запроса, функция запускается, и вывод отправляется в браузер.
Теперь проблема - вывод заголовков. В настоящее время для разработки я просто поставил строку перед вызовом runner()
, который выполняет print Content-type:text/html\n
- это, очевидно, немного ограничивает ..
Моей первой идеей было сделать так, чтобы функции возвращали dict, что-то вроде ..
@GET("/")
def index():
return {
"html": "<html><body>...</body></html>",
"headers": {"Location":"http://google.com"}
}
Мне действительно не нравится это - возвращать 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 "<html>"
print "<head><title>Something</title></head>"
print "<body>...</body>"
print "</html>
.. не беспокоясь о соединении нескольких строк вместе. В результате у меня мог бы быть отдельный поток для заголовков, так что вышеприведенная функция header()
записала бы в нее что-то вроде:
def header(name, value):
pyerweb.header_stream.write("%s: %s" % (name, value))
По сути, вопрос в том, как бы вы выводили заголовки из этой веб-платформы (в основном с точки зрения использования , но в меньшей степени реализации)?