Last active
August 29, 2015 14:17
-
-
Save adiroiban/621efeab47662a04cb20 to your computer and use it in GitHub Desktop.
Stop server HTTP transport
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Client which makes a simple POST request. | |
""" | |
import urllib | |
import urllib2 | |
params = urllib.urlencode( | |
{'action': 'delete-members', 'selected-members': 'README.rst'}) | |
req = urllib2.Request( | |
'http://127.0.0.1:8080/', | |
data=params, | |
) | |
try: | |
resp = urllib2.urlopen(req) | |
except Exception as error: | |
print "Error" | |
print error | |
else: | |
print "All good" | |
print resp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Server which stop reading client data after all headers are received | |
and continue reading data after the request has processed the data. | |
""" | |
from twisted.web import server, resource, http | |
from twisted.internet import reactor, defer | |
class HTTPProtocol(http.HTTPChannel): | |
__header = '' | |
def lineReceived(self, line): | |
""" | |
Code imported from HTTPChannel with minimal changes to support | |
deferred allHeadersReceived. | |
""" | |
print "GOT: %s" % line | |
self.resetTimeout() | |
if self._HTTPChannel__first_line: | |
# if this connection is not persistent, drop any data which | |
# the client (illegally) sent after the last request. | |
if not self.persistent: | |
self.dataReceived = self.lineReceived = lambda *args: None | |
return | |
# IE sends an extraneous empty line (\r\n) after a POST request; | |
# eat up such a line, but only ONCE | |
if not line and self._HTTPChannel__first_line == 1: | |
self._HTTPChannel__first_line = 2 | |
return | |
# create a new Request object | |
request = self.requestFactory(self, len(self.requests)) | |
self.requests.append(request) | |
self._HTTPChannel__first_line = 0 | |
parts = line.split() | |
if len(parts) != 3: | |
self.transport.write("HTTP/1.1 400 Bad Request\r\n\r\n") | |
self.transport.loseConnection() | |
return | |
command, request, version = parts | |
self._command = command | |
self._path = request | |
self._version = version | |
elif line == '': | |
if self.__header: | |
self.headerReceived(self.__header) | |
self.__header = '' | |
# Changes are here. | |
self.pauseProducing() | |
deferred = defer.maybeDeferred(self.allHeadersReceived) | |
def cb_headers_received(result): | |
""" | |
Called after successfully processing the headers. | |
""" | |
if self.length == 0: | |
self.allContentReceived() | |
else: | |
self.setRawMode() | |
self.resumeProducing() | |
def eb_headers_received(failure): | |
""" | |
Called when we fail to process headers. | |
""" | |
print failure.getBriefTraceback() | |
self.transport.write( | |
'HTTP/1.1 500 Internal Server Error\r\n\r\n') | |
self.transport.loseConnection() | |
deferred.addCallback(cb_headers_received) | |
deferred.addErrback(eb_headers_received) | |
# Changes end here. | |
elif line[0] in ' \t': | |
self.__header = self.__header + '\n' + line | |
else: | |
if self.__header: | |
self.headerReceived(self.__header) | |
self.__header = line | |
def allHeadersReceived(self): | |
def cb_allHeadersReceived(result): | |
# Code from HTPChannel.allHeadersReceived | |
print "Continue" | |
req = self.requests[-1] | |
req.parseCookies() | |
self.persistent = self.checkPersistence(req, self._version) | |
req.gotLength(self.length) | |
# Handle 'Expect: 100-continue' with automated 100 response code, | |
# a simplistic implementation of RFC 2686 8.2.3: | |
expectContinue = req.requestHeaders.getRawHeaders('expect') | |
if (expectContinue and expectContinue[0].lower() == '100-continue' and | |
self._version == 'HTTP/1.1'): | |
req.transport.write("HTTP/1.1 100 Continue\r\n\r\n") | |
# Delay the response from allHeadersReceived | |
deferred = defer.Deferred() | |
deferred.addCallback(cb_allHeadersReceived) | |
reactor.callLater(1, lambda: deferred.callback(None)) | |
return deferred | |
class Simple(resource.Resource): | |
isLeaf = True | |
def render_POST(self, request): | |
print "POST received" | |
request.setResponseCode(400) | |
return '' | |
site = server.Site(Simple()) | |
site.protocol = HTTPProtocol | |
reactor.listenTCP(8080, site) | |
reactor.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment