Example #1
0
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))
Example #2
0
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))
Example #3
0
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))
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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)
Example #9
0
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)
Example #10
0
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
Example #11
0
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
Example #12
0
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
Example #13
0
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)
Example #14
0
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)
Example #15
0
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