def _supported_httpmethods(cls, webmethodnames): """The HTTP methods that should be supported by this service .. note:: This does not return the same result as calling :meth:`_natural_httpmethod` on each of the given *webmethodnames*. Some allowed web methods imply support for more than their naturally corresponding HTTP method. :param webmethodnames: The names of the supported web methods. :type webmethodnames: ~[:obj:`str`] :rtype: {:obj:`str`} """ httpmethods = {cls._natural_httpmethod(methodname) for methodname in webmethodnames} # CAVEAT: expose HTTP POST as a means to submit long arguments to web # methods whose HTTP implementations do not reliably support message # bodies if any(not _http.method_defines_body_semantics(method) for method in httpmethods): httpmethods.add('POST') if 'GET' in httpmethods: httpmethods.add('HEAD') return httpmethods
def _request_webmethodname(cls, httpmethod, path, query): if httpmethod == 'HEAD': return 'get' # CAVEAT: examine the query string to convert HTTP POST to calls to # corresponding web method names whose HTTP implementations do not # reliably support message bodies if httpmethod == 'POST': query_method_pattern = r'^{}(&|$)' for name in (cls._webmethodname(httpmethod) for httpmethod in _http.METHODS if not _http.method_defines_body_semantics (httpmethod)): if _re.match(query_method_pattern.format(name), query): return name return httpmethod.lower()
def _request_body_args_prims_frombody(self, body, mediatype, httpmethod): # CAVEAT: handle the request body only for HTTP methods that define # semantics for the body. :rfc:`2616#section-4.3` recommends to # ignore message bodies for methods that do not specify semantics for # entity bodies if not _http.method_defines_body_semantics(httpmethod): return {} try: mediatype_name, _, _ = mediatype.partition(';') meth = self._request_body_args_prims_frombody_meth_by_mediatype\ [mediatype_name] except KeyError: supported_mediatypes = \ self._request_body_args_prims_frombody_func_by_mediatype.keys() raise ValueError('unsupported body media type {!r}: expecting one' ' of {}' .format(mediatype, supported_mediatypes)) return meth(self, body)
def __init__(self, method, uri, args=None, argtypes=None, args_as=None, accept_mediaranges=('application/json', '*/*; q=0.01'), auth=None, authtype='basic', origin=None, headers=None, **kwargs): method_kwargs = {} headers = _odict(headers or ()) method_kwargs['headers'] = headers if origin is not None: headers['Origin'] = origin headers.setdefault('Accept', ', '.join(accept_mediaranges)) if args: if argtypes: untyped_args = [arg for arg in args if arg not in argtypes] else: untyped_args = args.keys() if untyped_args: raise ValueError('missing type specifications for request' ' arguments {}'.format(untyped_args)) if args_as is None: if _http.method_defines_body_semantics(method.upper()): args_as = 'body' else: args_as = 'query' if args_as == 'query': args_json = {name: argtypes[name](value).json() for name, value in args.items()} method_kwargs['params'] = args_json elif args_as == 'body': args_webobjects = {name: argtypes[name](value) for name, value in args.items()} body = _webtypes.json_dumps(args_webobjects) method_kwargs['data'] = body headers['Content-Type'] = 'application/json' elif args_as == 'body_urlencoded': args_json = {name: argtypes[name](value).json() for name, value in args.items()} body = _urlencode(args_json) method_kwargs['data'] = body headers['Content-Type'] = 'application/x-www-form-urlencoded' else: raise ValueError('invalid argument mechanism {!r}; expected' ' one of {}' .format(args_as, ('query', 'body', 'body_urlencoded'))) if auth is not None: try: auth_class = _requests_auth_classmap[authtype] except KeyError: raise ValueError('invalid authentication type {!r}; expected' ' one of {}' .format(authtype, ('basic', 'digest'))) method_kwargs['auth'] = auth_class(*auth) method_kwargs.update(kwargs) super(WebRequest, self).__init__(method, uri, **method_kwargs)