Files
codeql/python/ql/test/library-tests/frameworks/twisted/response_test.py
Rasmus Wriedt Larsen e1af1f11ee Python: Add HTTP::Server::CookieWrite concept
along with tests, but no implementations (to ease reviewing).

---

I've put quite some thinking into what to call our concept for this.

[JS has `CookieDefinition`](581f4ed757/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll (L148-L187)), but I couldn't find a matching concept in any other languages.

We used to call this [`CookieSet`](f07a7bf8cf/python/ql/src/semmle/python/web/Http.qll (L76)) (and had a corresponding `CookieGet`).

But for headers, [Go calls this `HeaderWrite`](cd1e14ed09/ql/src/semmle/go/concepts/HTTP.qll (L97-L131)) and [JS calls this `HeaderDefinition`](581f4ed757/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll (L23-L46))

I think it would be really cool if we have a naming scheme that means the name for getting the value of a header on a incoming request is obvious. I think `HeaderWrite`/`HeaderRead` fulfils this best. We could go with `HeaderSet`/`HeaderGet`, but they feel a bit too vague to me. For me, I'm so used to talking about def-use, that I would immediately go for `HeaderDefinition` and `HeaderUse`, which could work, but is kinda strange.

So in the end that means I went with `CookieWrite`, since that allows using a consistent naming scheme for the future :)
2021-06-24 17:34:43 +02:00

80 lines
3.1 KiB
Python

from twisted.web.server import Site, Request, NOT_DONE_YET
from twisted.web.resource import Resource
from twisted.internet import reactor, endpoints, defer
root = Resource()
class Now(Resource):
def render(self, request: Request): # $ requestHandler
return b"now" # $ HttpResponse mimetype=text/html responseBody=b"now"
class AlsoNow(Resource):
def render(self, request: Request): # $ requestHandler
request.write(b"also now") # $ HttpResponse mimetype=text/html responseBody=b"also now"
return b"" # $ HttpResponse mimetype=text/html responseBody=b""
def process_later(request: Request):
print("process_later called")
request.write(b"later") # $ MISSING: responseBody=b"later"
request.finish()
class Later(Resource):
def render(self, request: Request): # $ requestHandler
# process the request in 1 second
print("setting up callback for process_later")
reactor.callLater(1, process_later, request)
return NOT_DONE_YET # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=NOT_DONE_YET
class PlainText(Resource):
def render(self, request: Request): # $ requestHandler
request.setHeader(b"content-type", "text/plain")
return b"this is plain text" # $ HttpResponse responseBody=b"this is plain text" SPURIOUS: mimetype=text/html MISSING: mimetype=text/plain
class Redirect(Resource):
def render_GET(self, request: Request): # $ requestHandler
request.redirect("/new-location") # $ HttpRedirectResponse redirectLocation="/new-location" HttpResponse mimetype=text/html
# By default, this `hello` output is not returned... not even when
# requested with curl.
return b"hello" # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=b"hello"
################################################################################
# Cookies
################################################################################
class CookieWriting(Resource):
"""Examples of providing values in response that is not in the body
"""
def render_GET(self, request: Request): # $ requestHandler
request.addCookie("key", "value") # $ MISSING: CookieWrite CookieName="key" CookieValue="value"
request.addCookie(k="key", v="value") # $ MISSING: CookieWrite CookieName="key" CookieValue="value"
request.cookies.append("key2=value") # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
request.responseHeaders.addRawHeader("key", "value")
request.setHeader("Set-Cookie", "key3=value3") # $ MISSING: CookieWrite CookieRawHeader="key3=value3"
return b"" # $ HttpResponse mimetype=text/html responseBody=b""
root.putChild(b"now", Now())
root.putChild(b"also-now", AlsoNow())
root.putChild(b"later", Later())
root.putChild(b"plain-text", PlainText())
root.putChild(b"redirect", Redirect())
root.putChild(b"setting_cookie", CookieWriting())
if __name__ == "__main__":
factory = Site(root)
endpoint = endpoints.TCP4ServerEndpoint(reactor, 8880)
endpoint.listen(factory)
print("Will run on http://localhost:8880")
reactor.run()