@@ -1074,10 +1074,10 @@ def parameter_hoisting_note(method: str,
1074
1074
def repository_search_spec (* , post : bool ):
1075
1075
id_spec_link = '#operations-Index-get_index__entity_type___entity_id_'
1076
1076
return {
1077
- 'summary' : fd ( f'''
1078
- Search an index for entities of interest
1079
- { ", with filters provided in the request body" if post else "" } .
1080
- ''' ),
1077
+ 'summary' : (
1078
+ ' Search an index for entities of interest' +
1079
+ iif ( post , ', with large parameters provided in the request body' )
1080
+ ),
1081
1081
'deprecated' : post ,
1082
1082
'description' :
1083
1083
iif (post , parameter_hoisting_note ('GET' , '/index/files' , 'POST' ) + fd ('''
@@ -1313,14 +1313,34 @@ def get_summary():
1313
1313
authentication = request .authentication )
1314
1314
1315
1315
1316
- def manifest_route (* , fetch : bool , initiate : bool ):
1316
+ post_manifest_example_url = (
1317
+ f'{ app .base_url } /manifest/files'
1318
+ f'?catalog={ list (config .catalogs .keys ())[0 ]} '
1319
+ '&filters={…}'
1320
+ f'&format={ app .metadata_plugin .manifest_formats [0 ].value } '
1321
+ )
1322
+
1323
+
1324
+ def manifest_route (* , fetch : bool , initiate : bool , curl : bool = False ):
1325
+ if initiate :
1326
+ if curl :
1327
+ assert not fetch
1328
+ method = 'POST'
1329
+ else :
1330
+ method = 'PUT'
1331
+ else :
1332
+ assert not curl
1333
+ method = 'GET'
1317
1334
return app .route (
1318
1335
# The path parameter could be a token *or* an object key, but we don't
1319
1336
# want to complicate the API with this detail
1320
1337
('/fetch' if fetch else '' )
1321
1338
+ ('/manifest/files' if initiate else '/manifest/files/{token}' ),
1322
1339
# The initial PUT request is idempotent.
1323
- methods = ['PUT' if initiate else 'GET' ],
1340
+ methods = [method ],
1341
+ # In order to support requests made with `curl` and its `--data` option,
1342
+ # we accept the `application/x-www-form-urlencoded` content-type.
1343
+ content_types = ['application/json' , 'application/x-www-form-urlencoded' ],
1324
1344
interactive = fetch ,
1325
1345
cors = True ,
1326
1346
path_spec = None if initiate else {
@@ -1332,26 +1352,58 @@ def manifest_route(*, fetch: bool, initiate: bool):
1332
1352
},
1333
1353
method_spec = {
1334
1354
'tags' : ['Manifests' ],
1355
+ 'deprecated' : curl ,
1335
1356
'summary' :
1336
1357
(
1337
1358
'Initiate the preparation of a manifest'
1338
1359
if initiate else
1339
1360
'Determine status of a manifest preparation job'
1340
1361
) + (
1341
1362
' via XHR' if fetch else ''
1363
+ ) + (
1364
+ ' as an alternative to PUT for curl users' if curl else ''
1342
1365
),
1343
- 'description' : fd ('''
1344
- Create a manifest preparation job, returning either
1345
-
1346
- - a 301 redirect to the URL of the status of that job or
1366
+ 'description' : (
1367
+ fd ('''
1368
+ Create a manifest preparation job, returning either
1347
1369
1348
- - a 302 redirect to the URL of an already prepared manifest.
1370
+ - a 301 redirect to the URL of the status of that job or
1349
1371
1350
- This endpoint is not suitable for interactive use via the
1351
- Swagger UI. Please use [PUT /fetch/manifest/files][1] instead.
1372
+ - a 302 redirect to the URL of an already prepared manifest.
1373
+ ''' )
1374
+ + iif (not curl , fd (f'''
1375
+ This endpoint is not suitable for interactive use via the
1376
+ Swagger UI. Please use [{ method } /fetch/manifest/files][1]
1377
+ instead.
1352
1378
1353
- [1]: #operations-Manifests-put_fetch_manifest_files
1354
- ''' ) + parameter_hoisting_note ('PUT' , '/manifest/files' , 'PUT' )
1379
+ [1]: #operations-Manifests-{ method .lower ()} _fetch_manifest_files
1380
+ ''' ))
1381
+ + parameter_hoisting_note (method , '/manifest/files' , method )
1382
+ + iif (curl , fd (f'''
1383
+ Requests to this endpoint are idempotent, so PUT would be
1384
+ the more standards-compliant method to use. POST is offered
1385
+ as a convenience for `curl` users, exploiting the fact that
1386
+ `curl` drops to GET when following a redirect in response to
1387
+ a POST, but not a PUT request. This is the only reason for
1388
+ the deprecation of this endpoint and there are currently no
1389
+ plans to remove it.
1390
+
1391
+ To use this endpoint with `curl`, pass the `--location` and
1392
+ `--data` options. This makes `curl` automatically follow the
1393
+ intermediate redirects to the GET /manifest/files endpoint,
1394
+ and ultimately to the URL that yields the manifest. Example:
1395
+
1396
+ ```
1397
+ curl --data "" --location { post_manifest_example_url }
1398
+ ```
1399
+
1400
+ In order to facilitate this, a POST request to this endpoint
1401
+ may have a `Content-Type` header of
1402
+ `application/x-www-form-urlencoded`, which is what the
1403
+ `--data` option sends. The body must be empty in that case
1404
+ and parameters cannot be hoisted as described above.
1405
+ ''' ))
1406
+ )
1355
1407
if initiate and not fetch else
1356
1408
fd ('''
1357
1409
Check on the status of an ongoing manifest preparation job,
@@ -1367,15 +1419,17 @@ def manifest_route(*, fetch: bool, initiate: bool):
1367
1419
instead.
1368
1420
1369
1421
[1]: #operations-Manifests-get_fetch_manifest_files__token_
1370
- ''' ) if not initiate and not fetch else fd ('''
1422
+ ''' )
1423
+ if not initiate and not fetch else
1424
+ fd (f'''
1371
1425
Create a manifest preparation job, returning a 200 status
1372
1426
response whose JSON body emulates the HTTP headers that would be
1373
- found in a response to an equivalent request to the [PUT
1427
+ found in a response to an equivalent request to the [{ method }
1374
1428
/manifest/files][1] endpoint.
1375
1429
1376
1430
Whenever client-side JavaScript code is used in a web
1377
1431
application to request the preparation of a manifest from Azul,
1378
- this endpoint should be used instead of [PUT
1432
+ this endpoint should be used instead of [{ method }
1379
1433
/manifest/files][1]. This way, the client can use XHR to make
1380
1434
the request, retaining full control over the handling of
1381
1435
redirects and enabling the client to bypass certain limitations
@@ -1385,8 +1439,9 @@ def manifest_route(*, fetch: bool, initiate: bool):
1385
1439
upper limit on the number of consecutive redirects, before the
1386
1440
manifest generation job is done.
1387
1441
1388
- [1]: #operations-Manifests-put_manifest_files
1389
- ''' ) + parameter_hoisting_note ('PUT' , '/fetch/manifest/files' , 'PUT' )
1442
+ [1]: #operations-Manifests-{ method .lower ()} _manifest_files
1443
+ ''' )
1444
+ + parameter_hoisting_note (method , '/fetch/manifest/files' , method )
1390
1445
if initiate and fetch else
1391
1446
fd ('''
1392
1447
Check on the status of an ongoing manifest preparation job,
@@ -1531,10 +1586,10 @@ def manifest_route(*, fetch: bool, initiate: bool):
1531
1586
1532
1587
For a detailed description of these properties see the
1533
1588
documentation for the respective response headers
1534
- documented under ''' ) + (fd ('''
1535
- [PUT /manifest/files][1].
1589
+ documented under ''' ) + (fd (f '''
1590
+ [{ method } /manifest/files][1].
1536
1591
1537
- [1]: #operations-Manifests-put_manifest_files
1592
+ [1]: #operations-Manifests-{ method . lower () } _manifest_files
1538
1593
''' ) if initiate else fd ('''
1539
1594
[GET /manifest/files/{token}][1].
1540
1595
@@ -1576,6 +1631,7 @@ def manifest_route(*, fetch: bool, initiate: bool):
1576
1631
)
1577
1632
1578
1633
1634
+ @manifest_route (fetch = False , initiate = True , curl = True )
1579
1635
@manifest_route (fetch = False , initiate = True )
1580
1636
def file_manifest ():
1581
1637
return _file_manifest (fetch = False )
@@ -1598,6 +1654,14 @@ def fetch_file_manifest_with_token(token: str):
1598
1654
1599
1655
def _file_manifest (fetch : bool , token_or_key : Optional [str ] = None ):
1600
1656
request = app .current_request
1657
+ post = request .method == 'POST'
1658
+ if (
1659
+ post
1660
+ and request .headers .get ('content-type' ) == 'application/x-www-form-urlencoded'
1661
+ and request .raw_body != b''
1662
+ ):
1663
+ raise BRE ('The body must be empty for a POST request of content-type '
1664
+ '`application/x-www-form-urlencoded` to this endpoint' )
1601
1665
query_params = request .query_params or {}
1602
1666
_hoist_parameters (query_params , request )
1603
1667
if token_or_key is None :
0 commit comments