Próbuję napisać filtr podobny do prostego opisanego w http://www.playframework.com/documentation/2.1.1/ScalaHttpFilters, ale muszę uzyskać dostęp do treści żądania. Poniższa dokumentacja stwierdza, że "kiedy przywołamy następną, otrzymamy z powrotem Iteratee.Możesz zawinąć to w Enumeratee, aby zrobić transformacje, jeśli chcesz." Próbuję dowiedzieć się, jak owinąć Iteratee, aby uzyskać treść żądania jako ciąg w filtrze, więc mogę to również zarejestrować.Scala odgrywa http filtry: jak znaleźć ciało żądania
Odpowiedz
Spędziłem trochę czasu na tym. Nie jestem ekspertem od Scali, ale działa to całkiem nieźle! :)
object AccessLog extends EssentialFilter {
def apply(nextFilter: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
val startTime = System.currentTimeMillis
nextFilter(requestHeader).map { result =>
val endTime = System.currentTimeMillis
val requestTime = endTime - startTime
val bytesToString: Enumeratee[ Array[Byte], String ] = Enumeratee.map[Array[Byte]]{ bytes => new String(bytes) }
val consume: Iteratee[String,String] = Iteratee.consume[String]()
val resultBody : Future[String] = result.body |>>> bytesToString &>> consume
resultBody.map {
body =>
Logger.info(s"${requestHeader.method} ${requestHeader.uri}" +
s" took ${requestTime}ms and returned ${result.header.status}")
val jsonBody = Json.parse(body)
Logger.debug(s"Response\nHeader:\n${result.header.headers.toString}\nBody:\n${Json.prettyPrint(jsonBody)}")
}
result.withHeaders("Request-Time" -> requestTime.toString)
}
}
}
Wynik końcowy wydrukuje ciało jako ciąg JSON (wydrukowany dość pięknie).
W Play 2.1.x ciało wartości nie jest członkiem play.api.mvc.Result –
Jestem w Play 2.2x http://www.playframework.com/documentation/2.2. x/api/scala/index.html # play.api.mvc.SimpleResult – Setheron
Przykro mi, ale to drukuje treść odpowiedzi na żądanie, a nie treść żądania –
W metodzie kontrolera, który kieruje do działania, wystarczy zadzwonić
Map<String, String[]> params = request().queryString();
To będzie Ci mapę parametrów, gdzie można następnie zadzwonić
params.get("someParam")[0]
uzyskać param (jeśli jest to pojedyncza wartość). Jeśli parametr jest listą, zignoruj indeksowanie i to zwróci tablicę.
Dzięki za odpowiedź, ale próbuję uzyskać dostęp do parametry w filtrze globalnym dla wszystkich żądań (wszystkie kontrolery i akcje ..etc), więc to nie zadziała. – Nonos
Pierwszą rzeczą, którą musisz wiedzieć, kiedy filtr jest wywoływany, treść żądania nie jest jeszcze przeanalizowana. Dlatego daje ci RequestHeader
. Musisz znaleźć typ ciała i odpowiednio wywołać odpowiedni parser ciała.
Możesz znaleźć przykład analizowania treści w filtrze CSRF (może wyszukiwać tokeny CSRF w pierwszych bajtach treści żądania).
Mam nadzieję, że to pomaga.
Wydaje się to bardzo pomocne. Muszę tylko przekonwertować treść na ciąg znaków w celu rejestrowania. Moja aplikacja zajmuje się głównie żądaniami GET lub POST z treścią JSON. – Nonos
Link do pliku źródłowego jest zepsuty –
Nie jestem pewien, czy rozumiem problem, ale jeśli masz prośbę, to uzyskanie ciała jest po prostu request.body ... – Jakob
Mam tylko nagłówek żądania, jak Julien stwierdził poniżej – Nonos
czy to działa? Jestem też ciekawy, jak to zrobić. – Setheron