docs: def request( self, url, method='get',
  			decode=None, encode=None, data=None,
  			headers=None, raise_for=dict(), queue_lines=None ):
  		'''Make HTTP(S) request.
  			headers can be either dict or callable(url, method, body, mimetype or None).
  			decode (response body) = None | json.
  			encode (data) = None | json | form | files.'''
  		if self.debug_requests:
  			url_debug = _dump_trunc(url)
  			log.debug('HTTP request: {} {} (h: {}, enc: {}, dec: {}, data: {!r})'.format(
  				method, url_debug, headers, encode, decode, _dump_trunc(data) ))
  
  		timeout = HTTPTimeout(**self.request_io_timeouts)
  		req_headers = {'User-Agent': 'txU1'}
  
  		if data is not None:
  			if encode == 'files':
  				boundary = os.urandom(16).encode('hex')
  				req_headers['Content-Type'] = 'multipart/form-data; boundary={}'.format(boundary)
  				data = MultipartDataSender(data, boundary)
  				if not callable(headers): yield data.calculate_length()
  				else:
  					body = io.BytesIO()
  					yield data.calculate_length(body)
  					headers = headers(url, method, body.getvalue(), 'multipart/form-data')
  			else:
  				if encode is None:
  					if isinstance(data, types.StringTypes): data = io.BytesIO(data)
  				elif encode == 'form':
  					req_headers['Content-Type'] = 'application/x-www-form-urlencoded'
  					data = io.BytesIO(urllib.urlencode(data))
  				elif encode == 'json':
  					req_headers['Content-Type'] = 'application/json'
  					data = io.BytesIO(json.dumps(data))
  				else: raise ValueError('Unknown request encoding: {}'.format(encode))
  				if callable(headers):
  					data.seek(0)
  					headers = headers(url, method, data.read(), req_headers.get('Content-Type'))
  				data = FileBodyProducer(data)
  		elif callable(headers): headers = headers(url, method, '', None)
  
  		# Passed "headers" should be allowed to be modified by body_hash()
  		for k, v in (headers or dict()).viewitems():
  			req_headers[force_bytes(k)] = force_bytes(v)
  		url, method = it.imap(force_bytes, [url, method.lower()])
  
  		if decode == 'json': req_headers.setdefault('Accept', 'application/json')
  		elif decode is not None:
  			raise ValueError('Unknown response decoding method: {}'.format(decode))
  
  		res_deferred = first_result( timeout,
  			self.request_agent.request( method.upper(), url,
  				Headers(dict((k,[v]) for k,v in req_headers.viewitems())), data ) )
  		code = res_body = None
  		try:
  			res = yield res_deferred
  			code = res.code
  			if code == http.NO_CONTENT: defer.returnValue(None)
  			if code not in [http.OK, http.CREATED]:
  				if self.debug_requests:
  					res_body = defer.Deferred()
  					res.deliverBody(DataReceiver(res_body, timer=timeout, allow_loss=True))
  					res_body = yield first_result(timeout, res_body)
  					log.debug('HTTP error response body: {!r}'.format(res_body))
  				raise ProtocolError(code, res.phrase)
  
  			res_body = defer.Deferred()
  			res.deliverBody(DataReceiver(res_body, timer=timeout))
  			res_body = yield first_result(timeout, res_body)
  
  			if self.debug_requests:
  				log.debug( 'HTTP request done ({} {}): {} {} {}, body_len: {}'\
  					.format(method, url_debug, code, res.phrase, res.version, len(res_body)) )
  			defer.returnValue(json.loads(res_body) if decode is not None else res_body)
  
  		except ( timeout.ActivityTimeout, TimeoutError,
  				ResponseFailed, RequestNotSent, RequestTransmissionFailed ) as err:
  			if isinstance(err, timeout.ActivityTimeout):
  				if not res_deferred.called: res_deferred.cancel()
  				if res_body and not res_body.called: res_body.cancel()
  			if self.debug_requests:
  				log.debug(
  					'HTTP transport (underlying protocol) error ({} {}): {}'\
  					.format(method, url_debug, err.message or repr(err.args)) )
  			raise UnderlyingProtocolError(err)
  
  		except ProtocolError as err:
  			if self.debug_requests:
  				log.debug(
  					'HTTP request handling error ({} {}, code: {}): {}'\
  					.format(method, url_debug, code, err.message) )
  			raise raise_for.get(code, ProtocolError)(code, err.message)
  
  		except RequestGenerationFailed as err:
  			err[0][0].raiseException()
  
  		finally: timeout.state_finished()