-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
109 lines (86 loc) · 3.48 KB
/
Copy pathmain.py
File metadata and controls
109 lines (86 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from os import getenv
from fastapi import FastAPI, HTTPException, Request, Response
from httpx import AsyncClient
from uvicorn import run as run_uvicorn
# Settings
OAI_ENDPOINT = getenv("OAI_ENDPOINT", "https://data.sciencespo.fr/oai")
OAI_ENDPOINT_DEV = getenv("OAI_ENDPOINT_DEV", "https://datapprd.sciencespo.fr/oai")
# We must change the endpoint in the response because of the pagination
ENDPOINT_MAPPING = {
OAI_ENDPOINT: "https://export-data.sciencespo.fr/oai",
OAI_ENDPOINT_DEV: "https://export-dataverse-pprd.cdsp.sciences-po.fr/oai",
}
# Mapping keys are used in the routes. Example: "/<key>/oai"
MAPPINGS = {
"rdg": {
"<dc:type>Audio</dc:type>": "<dc:type>Audiovisual</dc:type>",
"<dc:type>Geospatial</dc:type>": "<dc:type>Other</dc:type>",
"<dc:type>InteractiveResource</dc:type>": "<dc:type>Interactive Resource</dc:type>",
"<dc:type>Numeric</dc:type>": "<dc:type>Text</dc:type>",
# "<dc:type>Other</dc:type>": "<dc:type>Other</dc:type>",
# "<dc:type>Software</dc:type>": "<dc:type>Software</dc:type>",
"<dc:type>StillImage</dc:type>": "<dc:type>Image</dc:type>",
# "<dc:type>Text</dc:type>": "<dc:type>Text</dc:type>",
"<dc:type>ThreeD</dc:type>": "<dc:type>Audiovisual</dc:type>",
"<dc:type>Video</dc:type>": "<dc:type>Audiovisual</dc:type>",
},
}
# Initialize FastAPI and disable the documentation
app = FastAPI(docs_url=None, redoc_url=None)
# Initialize the asynchronous client
client = AsyncClient()
async def replace_content(content: str, mapping: dict) -> str:
"""Replace the content of a string using a dictionary"""
for old_value, new_value in mapping.items():
content = content.replace(old_value, new_value)
return content
async def handle_oai_response(
request: Request, oai_endpoint: str, mapping: dict
) -> Response:
"""Handle the OAI response"""
if not mapping:
raise HTTPException(status_code=404)
# Get the query to forward from the request
query = request.url.query
if not query:
raise HTTPException(status_code=400, detail="No query specified")
# Build the source path
source_path = f"{oai_endpoint}?{query}"
r = await client.get(source_path)
# If the status is not OK, use the same status code as the source and its reason phrase
if r.status_code != 200:
raise HTTPException(status_code=r.status_code, detail=r.reason_phrase)
# Replace the content of the response
content = await replace_content(r.text, mapping)
return Response(
headers={
# Cache for an hour
# "Cache-Control": "max-age=3600",
# Alternative location of the content (keep a link to the source)
"Content-Location": source_path,
},
media_type="application/xml",
content=content,
)
@app.get("/dev/{mapping}/oai")
async def oai_dev(mapping: str, request: Request) -> Response:
return await handle_oai_response(
request,
OAI_ENDPOINT_DEV,
{
OAI_ENDPOINT_DEV: ENDPOINT_MAPPING.get(OAI_ENDPOINT_DEV),
**MAPPINGS.get(mapping),
},
)
@app.get("/{mapping}/oai")
async def oai(mapping: str, request: Request) -> Response:
return await handle_oai_response(
request,
OAI_ENDPOINT,
{
OAI_ENDPOINT: ENDPOINT_MAPPING.get(OAI_ENDPOINT),
**MAPPINGS.get(mapping),
},
)
if __name__ == "__main__":
run_uvicorn(app, host="0.0.0.0", port=8000, reload=True)