1
- import os
2
1
from urllib .parse import parse_qs
3
2
4
- from dotenv import load_dotenv
5
3
from fastapi import APIRouter , Request , Query , HTTPException
6
4
7
- from jinja2 import Environment , FileSystemLoader
8
5
from starlette .responses import HTMLResponse
9
6
10
7
import logging
11
- from api .models .resolver import RapidResolverResponse , RapidResolverHtmlResponseType
12
- from core .logging import InterceptHandler
13
- from core .config import ENSEMBL_URL
14
- from api .utils .metadata import get_genome_id_from_assembly_accession_id
15
- from api .utils .rapid import construct_url , format_assembly_accession , construct_rapid_archive_url
8
+
9
+ from app .api .error_response import response_error_handler
10
+ from app .api .models .resolver import RapidResolverResponse , RapidResolverHtmlResponseType , SearchPayload , \
11
+ StableIdResolverResponse
12
+ from app .api .utils .commons import build_stable_id_resolver_content , is_json_request
13
+ from app .api .utils .metadata import get_genome_id_from_assembly_accession_id , get_metadata
14
+ from app .api .utils .rapid import format_assembly_accession , construct_rapid_archive_url , construct_url , \
15
+ generate_rapid_id_page , generate_rapid_page
16
+ from app .api .utils .search import get_search_results
17
+ from app .core .config import ENSEMBL_URL , RAPID_ARCHIVE_URL
18
+ from app .core .logging import InterceptHandler
16
19
17
20
logging .getLogger ().handlers = [InterceptHandler ()]
18
21
19
22
router = APIRouter ()
20
23
21
24
25
+ @router .get ("/id/{stable_id}" , name = "Resolve rapid stable ID" )
26
+ async def resolve_rapid_stable_id (request : Request , stable_id : str ):
27
+ # Handle only gene stable id for now
28
+ params = SearchPayload (stable_id = stable_id , type = "gene" , per_page = 10 )
29
+ search_results = get_search_results (params )
30
+ rapid_archive_url = f"{ RAPID_ARCHIVE_URL } /id/{ stable_id } "
31
+
32
+ if not search_results or not search_results .get ("matches" ):
33
+ if is_json_request (request ):
34
+ return response_error_handler ({"status" : 404 })
35
+ res = StableIdResolverResponse (
36
+ stable_id = stable_id ,
37
+ code = 404 ,
38
+ message = "No results" ,
39
+ content = None ,
40
+ rapid_archive_url = rapid_archive_url
41
+ )
42
+ return HTMLResponse (generate_rapid_id_page (res ))
43
+
44
+ matches = search_results .get ("matches" )
45
+ metadata_results = get_metadata (matches )
46
+
47
+ stable_id_resolver_response = StableIdResolverResponse (
48
+ stable_id = stable_id ,
49
+ code = 308 ,
50
+ rapid_archive_url = rapid_archive_url
51
+ )
52
+ results = build_stable_id_resolver_content (metadata_results )
53
+ stable_id_resolver_response .content = results
54
+
55
+ if is_json_request (request ):
56
+ return results
57
+
58
+ return HTMLResponse (generate_rapid_id_page (stable_id_resolver_response ))
59
+
60
+
22
61
@router .get ("/info/{subpath:path}" , name = "Resolve rapid help page" )
23
62
async def resolve_rapid_help (request : Request , subpath : str = "" ):
24
63
response = RapidResolverResponse (
25
64
response_type = RapidResolverHtmlResponseType .HELP ,
26
65
code = 308 ,
27
66
resolved_url = f"{ ENSEMBL_URL } /help" ,
28
67
)
29
- return resolved_response (response , request )
68
+ return rapid_resolved_response (response , request )
30
69
31
70
32
71
@router .get ("/Multi/Tools/Blast" , name = "Resolve rapid blast page" )
@@ -36,7 +75,7 @@ async def resolve_rapid_blast(request: Request):
36
75
code = 308 ,
37
76
resolved_url = f"{ ENSEMBL_URL } /blast" ,
38
77
)
39
- return resolved_response (response , request )
78
+ return rapid_resolved_response (response , request )
40
79
41
80
42
81
# Resolve rapid urls
@@ -53,7 +92,7 @@ async def resolve_species(
53
92
resolved_url = f"{ ENSEMBL_URL } /blast" ,
54
93
species_name = species_url_name ,
55
94
)
56
- return resolved_response (response , request )
95
+ return rapid_resolved_response (response , request )
57
96
58
97
assembly_accession_id = format_assembly_accession (species_url_name )
59
98
@@ -65,7 +104,7 @@ async def resolve_species(
65
104
message = "Invalid input accession ID" ,
66
105
species_name = species_url_name ,
67
106
)
68
- return resolved_response (input_error_response , request )
107
+ return rapid_resolved_response (input_error_response , request )
69
108
70
109
try :
71
110
genome_object = get_genome_id_from_assembly_accession_id (assembly_accession_id )
@@ -88,7 +127,7 @@ async def resolve_species(
88
127
location = query_params .get ("r" , [None ])[0 ],
89
128
rapid_archive_url = rapid_archive_url ,
90
129
)
91
- return resolved_response (response , request )
130
+ return rapid_resolved_response (response , request )
92
131
else :
93
132
raise HTTPException (status_code = 404 , detail = "Genome not found" )
94
133
except HTTPException as e :
@@ -100,7 +139,7 @@ async def resolve_species(
100
139
message = e .detail ,
101
140
species_name = species_url_name ,
102
141
)
103
- return resolved_response (response , request )
142
+ return rapid_resolved_response (response , request )
104
143
except Exception as e :
105
144
logging .debug (f"Unexpected error occurred: { e } " )
106
145
response = RapidResolverResponse (
@@ -110,7 +149,7 @@ async def resolve_species(
110
149
resolved_url = f"{ ENSEMBL_URL } /species-selector" ,
111
150
message = str (e ),
112
151
)
113
- return resolved_response (response , request )
152
+ return rapid_resolved_response (response , request )
114
153
115
154
116
155
@router .get ("/" , name = "Rapid Home" )
@@ -120,30 +159,15 @@ async def resolve_home(request: Request):
120
159
code = 308 ,
121
160
resolved_url = ENSEMBL_URL ,
122
161
)
123
- return resolved_response (response , request )
162
+ return rapid_resolved_response (response , request )
124
163
125
164
126
- def resolved_response (response : RapidResolverResponse , request : Request ):
127
- # Return JSON response if requested
128
- if "application/json" in request .headers .get ("accept" ):
129
- # Handle error responses for JSON requests
165
+ def rapid_resolved_response (response : RapidResolverResponse , request : Request ):
166
+ if is_json_request (request ):
130
167
if response .response_type == RapidResolverHtmlResponseType .ERROR :
131
168
raise HTTPException (
132
169
status_code = response .code ,
133
170
detail = response .message or "An error occurred" ,
134
171
)
135
- # Doesn't raise redirect for JSON requests, just return the URL. Because swagger UI doesn't handle redirects well.
136
- # So code is always 200 for successful JSON response.
137
- return response
138
-
139
- # Default to HTML response
140
- return HTMLResponse (generate_html_content (response ))
141
-
142
-
143
- def generate_html_content (response ):
144
- load_dotenv ()
145
- CURR_DIR = os .path .dirname (os .path .abspath (__file__ ))
146
- env = Environment (loader = FileSystemLoader (os .path .join (CURR_DIR , "templates/rapid" )))
147
- rapid_redirect_page_template = env .get_template ("main.html" )
148
- rapid_redirect_page_html = rapid_redirect_page_template .render (response = response )
149
- return rapid_redirect_page_html
172
+ return response .model_dump ()
173
+ return HTMLResponse (generate_rapid_page (response ))
0 commit comments