async def get(request: web.Request): hooks = request.app.hooks docid = request.match_info['dataset'] etag_if_none_match = conditional.parse_if_header( request, conditional.HEADER_IF_NONE_MATCH) if etag_if_none_match == '*': raise web.HTTPBadRequest( body='Endpoint does not support * in the If-None-Match header.') # Now we know etag_if_none_match is either None or a set. try: doc, etag = await hooks.storage_retrieve(app=request.app, docid=docid, etags=etag_if_none_match) except KeyError: raise web.HTTPNotFound() if doc is None: return web.Response(status=304, headers={'Etag': etag}) canonical_doc = await hooks.mds_canonicalize(app=request.app, data=doc) canonical_doc = await hooks.mds_after_storage(app=request.app, data=canonical_doc, doc_id=docid) if canonical_doc['ams:status'] not in ('beschikbaar', 'in_onderzoek'): scopes = request.authz_scopes if hasattr(request, "authz_scopes") else {} extra_read_access = 'CAT/R' in scopes if not extra_read_access: return web.HTTPForbidden() return web.json_response(canonical_doc, headers={ 'Etag': etag, 'content_type': 'application/ld+json' })
async def link_redirect(request: web.Request): dataset = request.match_info['dataset'] distribution = request.match_info['distribution'] etag_if_none_match = conditional.parse_if_header( request, conditional.HEADER_IF_NONE_MATCH) if etag_if_none_match == '*': raise web.HTTPBadRequest( body='Endpoint does not support * in the If-None-Match header.') try: doc, etag = await request.app.hooks.storage_retrieve( app=request.app, docid=dataset, etags=etag_if_none_match) except KeyError: raise web.HTTPNotFound() if doc is None: raise web.HTTPNotModified(headers={'ETag': etag}) headers = {'ETag': etag} resource_url = None for dist in doc.get('dcat:distribution', []): if dist.get('dc:identifier', None) == distribution: resource_url = dist.get('dcat:accessURL', None) break if resource_url is None: raise web.HTTPNotFound(headers=headers) raise web.HTTPTemporaryRedirect(location=resource_url, headers=headers)
async def delete(request: web.Request): given_id = request.match_info['dataset'] etag_if_match = conditional.parse_if_header(request, conditional.HEADER_IF_MATCH) if etag_if_match is None or etag_if_match == '*': raise web.HTTPBadRequest( text='Must provide a If-Match header containing one or more ETags.' ) try: await request.app.hooks.storage_delete(app=request.app, docid=given_id, etags=etag_if_match) except KeyError: raise web.HTTPNotFound() return web.Response(status=204, content_type='text/plain')
async def put(request: web.Request): hooks = request.app.hooks scopes = request.authz_scopes is_redact_only = 'CAT/W' not in scopes # Grab the document from the request body and canonicalize it. try: doc = await request.json() except json.decoder.JSONDecodeError: raise web.HTTPBadRequest(text='invalid json') doc['ams:modifiedby'] = request.authz_subject canonical_doc = await hooks.mds_canonicalize(app=request.app, data=doc) if is_redact_only and canonical_doc['ams:status'] == 'beschikbaar': raise web.HTTPForbidden() # Make sure the docid in the path corresponds to the ids given in the # document, if any. The assumption is that request.path (which corresponds # to the path part of the incoming HTTP request) is the path as seen by # the client. This is not necessarily true. doc_id = request.match_info['dataset'] # Let the metadata plugin grab the full-text search representation searchable_text = await hooks.mds_full_text_search_representation( data=canonical_doc) # Figure out the mode (insert / update) of the request. etag_if_match = conditional.parse_if_header(request, conditional.HEADER_IF_MATCH) etag_if_none_match = conditional.parse_if_header( request, conditional.HEADER_IF_NONE_MATCH) # Can't accept a value in both headers if etag_if_match is not None and etag_if_none_match is not None: raise web.HTTPBadRequest( body='Endpoint supports either If-Match or If-None-Match in a ' 'single request, not both') # If-Match: {etag, ...} is for updates if etag_if_match is not None: if etag_if_match == '*': raise web.HTTPBadRequest( body='Endpoint does not support If-Match: *. Must provide one ' 'or more Etags.') try: old_doc, _etag = await hooks.storage_retrieve(app=request.app, docid=doc_id, etags=None) except KeyError: _logger.exception('precondition failed') raise web.HTTPPreconditionFailed() canonical_doc = await hooks.mds_before_storage(app=request.app, data=canonical_doc, old_data=old_doc) try: new_etag = await hooks.storage_update( app=request.app, docid=doc_id, doc=canonical_doc, searchable_text=searchable_text, etags=etag_if_match, iso_639_1_code="nl") except ValueError: _logger.exception('precondition failed') raise web.HTTPPreconditionFailed() await notify_data_changed(request.app) retval = web.Response(status=204, headers={'Etag': new_etag}) else: # If-None-Match: * is for creates if etag_if_none_match != '*': raise web.HTTPBadRequest( body='For inserts of new documents, provide If-None-Match: *') canonical_doc = await hooks.mds_before_storage(app=request.app, data=canonical_doc) try: new_etag = await hooks.storage_create( app=request.app, docid=doc_id, doc=canonical_doc, searchable_text=searchable_text, iso_639_1_code="nl") except KeyError: _logger.exception('precondition failed') raise web.HTTPPreconditionFailed() await notify_data_changed(request.app) retval = web.Response(status=201, headers={'Etag': new_etag}, content_type='text/plain') return retval