def post_media(request): """ Post the media. Args: request (HTTPRequest): The HTTP request Return: a HTTPResponse """ LOGGING.info("Post media") _doi = get_doi_from_request(request, "media") if _doi is None: return get_response("Bad Request - doi not found in URL", 400) LOGGING.debug("Post media, doi: %s", _doi) try: doi_suffix = _doi.split(DOI_PREFIX, 1)[1] except IndexError: return get_response( "Bad Request - wrong prefix, doi should start " "with %s" % DOI_PREFIX, 400) if not is_authorized(request, doi_suffix): return get_response("Unauthorized - insufficient privileges", 403) url = urljoin(DATACITE_URL, request.get_full_path()) return _post(url, request.body, _get_content_type_header(request))
def post_metadata(request): """ Post the metadata. Args: request (HTTPRequest): The HTTP request Return: a HTTPResponse """ LOGGING.info('Post metadata') try: _doi = _get_doi_from_xml_body(request.body) except ET.ParseError as ex: LOGGING.info('Error parsing xml from users request: %s', ex) return get_response("Bad Request - error parsing xml: %s" % ex, 400) if _doi == None: return get_response("Bad Request - doi not found in XML", 400) LOGGING.debug('Post metadata, doi: %s', _doi) try: doi_suffix = _doi.split(DOI_PREFIX, 1)[1] except IndexError: return get_response("Bad Request - wrong prefix, doi should start " \ "with %s" % DOI_PREFIX, 400) if not is_authorized(request, doi_suffix): return get_response("Unauthorized - insufficient privileges", 403) url = urljoin(DATACITE_URL, request.get_full_path()) return _post(url, request.body, _get_content_type_header(request))
def post_doi(request): """ Post the DOI. Args: request (HTTPRequest): The HTTP request Return: a HTTPResponse """ LOGGING.info('Post doi') try: _doi = _get_doi_from_text_body(request.body) except IndexError: return get_response("Bad Request - request body must be exactly two " \ "lines: DOI and URL", 400) LOGGING.debug('Post doi, doi: %s', _doi) try: doi_suffix = _doi.split(DOI_PREFIX, 1)[1] except IndexError: return get_response("Bad Request - wrong prefix, doi should start " \ "with %s" % DOI_PREFIX, 400) if not is_authorized(request, doi_suffix): return get_response("Unauthorized - insufficient privileges", 403) url = urljoin(DATACITE_URL, request.get_full_path()) return _post(url, request.body, _get_content_type_header(request))
def _post(url, body, headers): """ Send a post request to DataCite. Args: url (str): The URL to call body (str): The data headers (dict): A dictionary of headers to use Return: a HTTPResponse """ _set_timeout() opener = get_opener() auth_string = (base64.encodestring(DATACITE_USER_NAME + ':' + DATACITE_PASSWORD)).rstrip() headers.update({'Authorization':'Basic ' + auth_string}) # If the request body is a string, urllib2 attempts to concatenate the url, # body and headers. If the url is unicode, the request body can get # converted unicode. This has resulted in issues where there are characters # with diacritic marks in the request body. To avoid these issues the url is # UTF-8 encoded. url_encode = url.encode('utf-8') req = urllib2.Request(url_encode, data=body, headers=headers) try: response = opener.open(req) except (urllib2.HTTPError) as ex: msg = ex.readlines() LOGGING.warn('HTTPError error getting %s. %s', url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib2.URLError) as ex: LOGGING.warn('Timeout or URLError error getting %s. %s', url, ex.reason) return get_response(ex.reason, 500) except (SSLError) as ex: LOGGING.warn('SSLError error getting %s. %s', url, ex) return get_response(ex, 500) except UnicodeDecodeError as ex: LOGGING.info('UnicodeDecodeError error getting %s. %s', url, ex) return get_response(ex, 500) finally: _close(opener) if response.headers.has_key('Content-Type'): ret_response = HttpResponse(content_type= response.headers.get('Content-Type')) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) if response.headers.has_key('location'): ret_response.setdefault('Location', response.headers.get('location')) return ret_response
def get(request_method, url, headers): """ Send a get or head request to DataCite. Args: request_method (str): This should be 'GET' or 'HEAD' url (str): The URL to call headers (dict): A dictionary of headers to use Return: a HTTPResponse """ LOGGING.info("get(%s,%s,%s)", request_method, url, headers) _set_timeout() opener = get_opener() auth_string = ((base64.encodebytes( (DATACITE_USER_NAME + ":" + DATACITE_PASSWORD).encode())).decode("utf-8").rstrip()) headers.update({"Authorization": "Basic " + auth_string}) req = urllib.request.Request(url, data=None, headers=headers) if request_method == "HEAD": req.get_method = lambda: "HEAD" try: response = opener.open(req) except urllib.error.HTTPError as ex: msg = ex.readlines() if ex.code in [404, 410]: LOGGING.info("HTTPError error getting %s. %s", url, msg) else: LOGGING.warning("HTTPError error getting %s. %s", url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib.error.URLError) as ex: LOGGING.warning("Timeout or URLError error getting %s. %s", url, ex.reason) if isinstance(ex.reason, Exception): ex = ex.reason LOGGING.warning("Nested exception %s. %s", ex, ex.reason) return get_response(ex.reason, 500) except SSLError as ex: LOGGING.warning("SSLError error getting %s. %s", url, ex) return get_response(ex, 500) finally: _close(opener) if "Content-Type" in response.headers: ret_response = HttpResponse( content_type=response.headers.get("Content-Type")) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) return ret_response
def get(request_method, url, headers): """ Send a get or head request to DataCite. Args: request_method (str): This should be 'GET' or 'HEAD' url (str): The URL to call headers (dict): A dictionary of headers to use Return: a HTTPResponse """ LOGGING.info('get(%s,%s,%s)', request_method, url, headers) _set_timeout() opener = get_opener() auth_string = (base64.encodestring(DATACITE_USER_NAME + ':' + DATACITE_PASSWORD)).rstrip() headers.update({'Authorization': 'Basic ' + auth_string}) req = urllib2.Request(url, data=None, headers=headers) if request_method == "HEAD": req.get_method = lambda: 'HEAD' try: response = opener.open(req) except (urllib2.HTTPError) as ex: msg = ex.readlines() if ex.code in [404, 410]: LOGGING.info('HTTPError error getting %s. %s', url, msg) else: LOGGING.warn('HTTPError error getting %s. %s', url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib2.URLError) as ex: LOGGING.warn('Timeout or URLError error getting %s. %s', url, ex.reason) return get_response(ex.reason, 500) except (SSLError) as ex: LOGGING.warn('SSLError error getting %s. %s', url, ex) return get_response(ex, 500) finally: _close(opener) if response.headers.has_key('Content-Type'): ret_response = HttpResponse( content_type=response.headers.get('Content-Type')) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) return ret_response
def get(request_method, url, headers): """ Send a get or head request to DataCite. Args: request_method (str): This should be 'GET' or 'HEAD' url (str): The URL to call headers (dict): A dictionary of headers to use Return: a HTTPResponse """ LOGGING.info('get(%s,%s,%s)', request_method, url, headers) _set_timeout() opener = get_opener() auth_string = (base64.encodestring(DATACITE_USER_NAME + ':' + DATACITE_PASSWORD)).rstrip() headers.update({'Authorization':'Basic ' + auth_string}) req = urllib2.Request(url, data=None, headers=headers) if request_method == "HEAD": req.get_method = lambda: 'HEAD' try: response = opener.open(req) except (urllib2.HTTPError) as ex: msg = ex.readlines() if ex.code in [404, 410]: LOGGING.info('HTTPError error getting %s. %s', url, msg) else: LOGGING.warn('HTTPError error getting %s. %s', url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib2.URLError) as ex: LOGGING.warn('Timeout or URLError error getting %s. %s', url, ex.reason) return get_response(ex.reason, 500) except (SSLError) as ex: LOGGING.warn('SSLError error getting %s. %s', url, ex) return get_response(ex, 500) finally: _close(opener) if response.headers.has_key('Content-Type'): ret_response = HttpResponse(content_type= response.headers.get('Content-Type')) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) return ret_response
def post_doi(request, method="POST"): """ Post the DOI. Args: request (HTTPRequest): The HTTP request Return: a HTTPResponse """ LOGGING.info("Post doi") try: _doi = _get_doi_from_text_body(request.body.decode("utf-8")) except IndexError: return get_response( "Bad Request - request body must be exactly two " "lines: DOI and URL", 400) LOGGING.debug("Post doi, doi: %s", _doi) try: doi_suffix = _doi.split(DOI_PREFIX, 1)[1] except IndexError: return get_response( "Bad Request - wrong prefix, doi should start " "with %s" % DOI_PREFIX, 400) try: # The URL can contain the DOI - check that it matches url_doi = request.get_full_path().split("doi/", 1)[1] if len(url_doi) > 0 and url_doi != _doi: return get_response( "Bad Request - DOI in URL does not match DOI in request body\n", 400) except IndexError: # There is no DOI in the URL, which is fine pass if not is_authorized(request, doi_suffix): return get_response("Unauthorized - insufficient privileges", 403) url = urljoin(DATACITE_URL, request.get_full_path()) return _post(url, request.body, _get_content_type_header(request), method=method)
def post_metadata(request, method="POST"): """ Post the metadata. Args: request (HTTPRequest): The HTTP request Return: a HTTPResponse """ LOGGING.info("Post metadata") try: _doi = _get_doi_from_xml_body(request.body) except ET.ParseError as ex: LOGGING.info("Error parsing xml from users request: %s", ex) return get_response("Bad Request - error parsing xml: %s" % ex, 400) if _doi is None: return get_response("Bad Request - doi not found in XML", 400) LOGGING.debug("Post metadata, doi: %s", _doi) try: doi_suffix = _doi.split(DOI_PREFIX, 1)[1] except IndexError: return get_response( "Bad Request - wrong prefix, doi should start " "with %s" % DOI_PREFIX, 400) try: # The URL can contain the DOI - check that it matches the metadata url_doi = request.get_full_path().split("metadata/", 1)[1] if len(url_doi) > 0 and url_doi != _doi: return get_response( "Bad Request - DOI in URL does not match " "DOI in metadata\n", 400) except IndexError: # There is no DOI in the URL, which is fine pass if not is_authorized(request, doi_suffix): return get_response("Unauthorized - insufficient privileges", 403) url = urljoin(DATACITE_URL, request.get_full_path()) return _post(url, request.body, _get_content_type_header(request), method=method)
def _delete(url): """ Send a delete request to DataCite. Args: url (str): The URL to call Return: a HTTPResponse """ _set_timeout() opener = get_opener() auth_string = ((base64.encodebytes( (DATACITE_USER_NAME + ":" + DATACITE_PASSWORD).encode())).decode("utf-8").rstrip()) headers = {"Authorization": "Basic " + auth_string} req = urllib.request.Request(url, data=None, headers=headers) req.get_method = lambda: "DELETE" try: response = opener.open(req) except urllib.error.HTTPError as ex: msg = ex.readlines() LOGGING.warning("HTTPError error getting %s. %s", url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib.error.URLError) as ex: LOGGING.warning("Timeout or URLError error getting %s. %s", url, ex.reason) return get_response(ex.reason, 500) except SSLError as ex: LOGGING.warning("SSLError error getting %s. %s", url, ex) return get_response(ex, 500) finally: _close(opener) if "Content-Type" in response.headers: ret_response = HttpResponse( content_type=response.headers.get("Content-Type")) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) return ret_response
def _delete(url): """ Send a delete request to DataCite. Args: url (str): The URL to call Return: a HTTPResponse """ _set_timeout() opener = get_opener() auth_string = (base64.encodestring(DATACITE_USER_NAME + ':' + DATACITE_PASSWORD)).rstrip() headers = {'Authorization': 'Basic ' + auth_string} req = urllib2.Request(url, data=None, headers=headers) req.get_method = lambda: 'DELETE' try: response = opener.open(req) except (urllib2.HTTPError) as ex: msg = ex.readlines() LOGGING.warn('HTTPError error getting %s. %s', url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib2.URLError) as ex: LOGGING.warn('Timeout or URLError error getting %s. %s', url, ex.reason) return get_response(ex.reason, 500) except (SSLError) as ex: LOGGING.warn('SSLError error getting %s. %s', url, ex) return get_response(ex, 500) finally: _close(opener) if response.headers.has_key('Content-Type'): ret_response = HttpResponse( content_type=response.headers.get('Content-Type')) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) return ret_response
def _delete(url): """ Send a delete request to DataCite. Args: url (str): The URL to call Return: a HTTPResponse """ _set_timeout() opener = get_opener() auth_string = (base64.encodestring(DATACITE_USER_NAME + ':' + DATACITE_PASSWORD)).rstrip() headers = {'Authorization':'Basic ' + auth_string} req = urllib2.Request(url, data=None, headers=headers) req.get_method = lambda: 'DELETE' try: response = opener.open(req) except (urllib2.HTTPError) as ex: msg = ex.readlines() LOGGING.warn('HTTPError error getting %s. %s', url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib2.URLError) as ex: LOGGING.warn('Timeout or URLError error getting %s. %s', url, ex.reason) return get_response(ex.reason, 500) except (SSLError) as ex: LOGGING.warn('SSLError error getting %s. %s', url, ex) return get_response(ex, 500) finally: _close(opener) if response.headers.has_key('Content-Type'): ret_response = HttpResponse(content_type= response.headers.get('Content-Type')) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) return ret_response
def delete_metadata(request): """ Delete the metadata for the DOI. Args: request (HTTPRequest): The HTTP request Return: a HTTPResponse """ _doi = get_doi_from_request(request, 'metadata') LOGGING.info('Delete metadata doi: %s', _doi) url = urljoin(DATACITE_URL, request.get_full_path()) try: doi_suffix = _doi.split(DOI_PREFIX, 1)[1] except IndexError: return get_response("Bad Request - wrong prefix, doi should start " \ "with %s" % DOI_PREFIX, 400) if not is_authorized(request, doi_suffix): return get_response("Unauthorized - insufficient privileges", 403) return _delete(url)
def _post(url, body, headers, method="POST"): """ Send a post request to DataCite. Args: url (str): The URL to call body (str): The data headers (dict): A dictionary of headers to use Return: a HTTPResponse """ _set_timeout() opener = get_opener() auth_string = ((base64.encodebytes( (DATACITE_USER_NAME + ":" + DATACITE_PASSWORD).encode())).decode("utf-8").rstrip()) headers.update({"Authorization": "Basic " + auth_string}) # If the request body is a string, urllib2 attempts to concatenate the url, # body and headers. If the url is unicode, the request body can get # converted unicode. This has resulted in issues where there are characters # with diacritic marks in the request body. To avoid these issues the url is # UTF-8 encoded. url_encode = url.encode("utf-8").decode() req = urllib.request.Request(url_encode, data=body, headers=headers, method=method) try: response = opener.open(req) except urllib.error.HTTPError as ex: msg = ex.readlines() LOGGING.warning("HTTPError error getting %s. %s", url, msg) return get_response(msg, ex.code) except (socket.timeout, urllib.error.URLError) as ex: LOGGING.warning("Timeout or URLError error getting %s. %s", url, ex.reason) return get_response(ex.reason, 500) except SSLError as ex: LOGGING.warning("SSLError error getting %s. %s", url, ex) return get_response(ex, 500) except UnicodeDecodeError as ex: LOGGING.info("UnicodeDecodeError error getting %s. %s", url, ex) return get_response(ex, 500) finally: _close(opener) if "Content-Type" in response.headers: ret_response = HttpResponse( content_type=response.headers.get("Content-Type")) else: ret_response = HttpResponse() ret_response.status_code = response.code ret_response.reason_phrase = response.msg # pylint: disable=maybe-no-member ret_response.writelines(response.readlines()) if "location" in response.headers: ret_response.setdefault("Location", response.headers.get("location")) return ret_response