Skip to content

Instantly share code, notes, and snippets.

@adiroiban
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adiroiban/621efeab47662a04cb20 to your computer and use it in GitHub Desktop.
Save adiroiban/621efeab47662a04cb20 to your computer and use it in GitHub Desktop.
Stop server HTTP transport
"""
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
"""
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