2014-02-13 5 views
4

У меня есть следующие веб-приложение:Доступ объект ответа в bottlepy after_request крючок

import bottle 
app = bottle.Bottle() 

@app.route('/ping') 
def ping(): 
    print 'pong' 
    return 'pong' 

@app.hook('after_request') 
def after(): 
    print 'foo' 
    print bottle.response.body 

if __name__ == "__main__": 
    app.run(host='0.0.0.0', port='9999', server='cherrypy') 

Есть ли способ получить доступ к телу ответа, прежде чем отправить ответ обратно?

Если я запустить приложение и я запрашиваю /ping, я могу видеть в консоли, что ping() и after() функции выполняются в правильной последовательности

$ python bottle_after_request.py 
Bottle v0.11.6 server starting up (using CherryPyServer())... 
Listening on http://0.0.0.0:9999/ 
Hit Ctrl-C to quit. 

pong 
foo 

но когда в after() попытке получить доступ к response.body, я ничего не имеют.

В Flask функции after_request, украшенные функцией, принимают входной объект ответа, поэтому его легко получить. Как я могу сделать то же самое в бутылке?

Есть ли что-то, что мне не хватает?

ответ

4

Есть ли способ получить доступ к телу ответа перед отправкой ответа назад?

Вы можете написать простой плагин, который (в зависимости от того, что вы на самом деле пытаетесь сделать с ответом) может быть всем, что вам нужно.

Вот пример из Bottle plugin docs, который устанавливает заголовок запроса. Он мог так же легко манипулировать body.

from bottle import response, install 
import time 

def stopwatch(callback): 
    def wrapper(*args, **kwargs): 
     start = time.time() 
     body = callback(*args, **kwargs) 
     end = time.time() 
     response.headers['X-Exec-Time'] = str(end - start) 
     return body 
    return wrapper 

install(stopwatch) 

Надеюсь, что это сработает для ваших целей.

+0

Плагины не вызываются для запросов, которые не соответствуют ни одному маршруту. Таким образом, это делает их непригодными для создания журнала доступа, например. –

1

Вы можете использовать плагин подхода, это то, что я сделал

from bottle import response 


class BottlePlugin(object): 

    name = 'my_custom_plugin' 
    api = 2 

    def __init__(self, debug=False): 
     self.debug = debug 
     self.app = None 

    def setup(self, app): 
     """Handle plugin install""" 
     self.app = app 

    def apply(self, callback): 
     """Handle route callbacks""" 
     def wrapper(*a, **ka): 
      """Encapsulate the result in the expected api structure""" 
      # Check if the client wants a different format 

      # output depends what you are returning from view 
      # in my case its dict with keys ("data") 
      output = callback(*a, **ka) 
      data = output["data"] 
      paging = output.get("paging", {}) 

      response_data = { 
       data: data, 
       paging: paging 
      } 
      # in case if you want to update response 
      # e.g response code 
      response.status = 200 

      return response_data 

     return wrapper 
Смежные вопросы