|
5 | 5 | import urllib |
6 | 6 | import itertools |
7 | 7 | import os |
| 8 | +from starlette.middleware.cors import CORSMiddleware |
8 | 9 |
|
9 | 10 | ALLOWED_URLS = os.environ.get("ALLOWED_URLS", "").split(",") |
| 11 | +ALLOWED_ORIGINS_ENV = os.environ.get("ALLOWED_ORIGINS", "*") |
10 | 12 |
|
11 | 13 | app = FastAPI() |
12 | 14 |
|
| 15 | +# Configure CORS |
| 16 | +_origins = [o.strip() for o in ALLOWED_ORIGINS_ENV.split(",") if o.strip()] |
| 17 | +_allow_origins = ["*"] if not _origins or _origins == ["*"] else _origins |
| 18 | +app.add_middleware( |
| 19 | + CORSMiddleware, |
| 20 | + allow_origins=_allow_origins, |
| 21 | + allow_credentials=True, |
| 22 | + allow_methods=["*"], |
| 23 | + allow_headers=["*"], |
| 24 | +) |
| 25 | + |
13 | 26 | def check_url(url): |
14 | 27 | url = urllib.parse.unquote(url) |
15 | 28 | if not any(url.startswith(allowed_url) for allowed_url in ALLOWED_URLS): |
@@ -149,6 +162,31 @@ def vcf_contigs(url: str): |
149 | 162 | except OSError as e: |
150 | 163 | send_400_resp(f"Unable to open file: {e}") |
151 | 164 |
|
| 165 | +@app.get("/vcf/fetch/{seqid}:{start}-{end}/{strains}/{url:path}") |
| 166 | +def vcf_features(url: str, seqid: str, start: int, end: int, strains: str): |
| 167 | + try: |
| 168 | + samples = [s.strip() for s in strains.split(",") if s.strip()] |
| 169 | + vf = pysam.VariantFile(check_url(url)) |
| 170 | + if samples: |
| 171 | + vf.subset_samples(samples) |
| 172 | + return [ {"chrom": feature.chrom, |
| 173 | + "pos": feature.pos, |
| 174 | + "id": feature.id, |
| 175 | + "ref": feature.ref, |
| 176 | + "alts": feature.alts, |
| 177 | + "qual": feature.qual, |
| 178 | + "filter": list(feature.filter), |
| 179 | + "info": list(feature.info), |
| 180 | + "format": list(feature.format), |
| 181 | + "samples": list(feature.samples), |
| 182 | + "alleles": feature.alleles} |
| 183 | + for feature |
| 184 | + in vf.fetch(seqid, start, end) ] |
| 185 | + except OSError as e: |
| 186 | + send_400_resp(f"Unable to open file: {e}") |
| 187 | + except KeyError as e: |
| 188 | + send_400_resp(f"Unable to find feature: {e}") |
| 189 | + |
152 | 190 | @app.get("/vcf/fetch/{seqid}:{start}-{end}/{url:path}") |
153 | 191 | def vcf_features(url: str, seqid: str, start: int, end: int): |
154 | 192 | try: |
|
0 commit comments