Reputation: 23
I'm encountering issues when trying to use my Flask app deployed in Vercel. It is a small program that returns a badge containing the number of stars a GitHub repo has.
import requests
from flask import Flask, Response
app = Flask(__name__, template_folder='dynamicBadges/templateFiles', static_folder='dynamicBadges/staticFiles')
# VARIANT 1 ----------------------------------------------------------------
variant_1 = ['#B02E26', '#974800', '#8E7500', '3F6900', '#4B6700', '#00696A', '#4B53B9', '#006493', '#8A33B8', '#9E2A99', '#99405E', '#1B1B1B']
on_variant_1 = '#FFF'
# VARIANT 2 ----------------------------------------------------------------
variant_2 = ['#FFB4AA', '#FFB689', '#E9C327', '#92DA35', '#AFD364', '#4CDADB', '#BEC2FF', '#8DCDFF', '#E8B3FF', '#FFABF1', '#FFB1C5', '#C6C6C6']
on_variant_2 = ['#690004', '#512400', '#3B2F00', '#1F3700', '#253600', '#003737', '#181F89', '#00344F', '#500075', '#5C005A', '#5E1130', '#303030']
# VARIANT 3 ----------------------------------------------------------------
variant_3 = ['#FFDAD5', '#FFDBC7', '#FFE177', '#ACF850', '#CAF07D', '#6FF6F7', '#E0E0FF', '#CAE6FF', '#F6D9FF', '#FFD7F4', '#FFD9E1', '#E2E2E2']
on_variant_3 = ['#410001', '#311300', '#231B00', '#102000', '#141F00', '#002020', '#00036B', '#001E30', '#310049', '#380037', '#3F001B', '#1B1B1B']
@app.route('/badge/stars/<style>/<variant>/<username>/<repo>')
def github_stars_badge(style, variant, username, repo):
url = f'https://api.github.com/repos/{username}/{repo}'
headers = {'Accept': 'application/vnd.github.v3+json'}
r = requests.get(url, headers=headers)
if r.ok:
index = int(style) - 1
if variant == '1':
background = variant_1[index]
foreground = on_variant_1
if variant == '2':
background = variant_2[index]
foreground = on_variant_2[index]
if variant == '3':
background = variant_3[index]
foreground = on_variant_3[index]
data = r.json()
stars = data['stargazers_count']
if len(str(stars)) == 1:
width = 20 + 68
elif len(str(stars)) == 2:
width = 2 * 16 + 68
elif len(str(stars)) == 3:
width = 3 * 14 + 68
elif len(str(stars)) == 4:
width = 4 * 13 + 68
else:
width = len(str(stars)) * 13 + 68
svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="30" fill="{background}" rx="15"><path d="M40 0h4v20h-4z" fill="#4c1"/><rect rx="15" width="{width}" height="30" fill="{background}"/><text x="11" y="22" fill="{foreground}" font-size="20" font-family="Product Sans">Stars : {stars}</text></svg>'
return Response(svg, mimetype='image/svg+xml')
else:
return 'Error', r.status_code
{
"version": 2,
"builds": [
{
"src": "dynamicBadges",
"use": "@vercel/python",
"config": {
"maxLambdaSize": "15mb"
}
}
],
"routes": [
{
"src": "/badge/stars/(.*)/(.*)/(.*)/(.*)",
"dest": "dynamicBadges/main.py"
}
]
}
Flask==2.3.2
Something like this : expecting
(but in this case with the number of stars the VsCode repo on GitHub has)
Thanks.
Upvotes: 2
Views: 704
Reputation: 13661
As you are using requests
package, this should be added to requirements.txt
. Also the vercel.json
should have correct source and destination paths of the routes.
Directory structure:
.
├── api
│ └── index.py
├── README.md
├── requirements.txt
└── vercel.json
Updated requirements.txt
:
blinker==1.6.2
certifi==2023.5.7
charset-normalizer==3.1.0
click==8.1.3
Flask==2.3.2
idna==3.4
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
requests==2.31.0
urllib3==2.0.3
Werkzeug==2.3.6
Updated vercel.json
:
{
"rewrites": [
{ "source": "/(.*)", "destination": "/api/index" }
]
}
/api/index.py
:
import requests
from flask import Flask, Response
app = Flask(__name__, template_folder='dynamicBadges/templateFiles', static_folder='dynamicBadges/staticFiles')
# VARIANT 1 ----------------------------------------------------------------
variant_1 = ['#B02E26', '#974800', '#8E7500', '3F6900', '#4B6700', '#00696A', '#4B53B9', '#006493', '#8A33B8',
'#9E2A99', '#99405E', '#1B1B1B']
on_variant_1 = '#FFF'
# VARIANT 2 ----------------------------------------------------------------
variant_2 = ['#FFB4AA', '#FFB689', '#E9C327', '#92DA35', '#AFD364', '#4CDADB', '#BEC2FF', '#8DCDFF', '#E8B3FF',
'#FFABF1', '#FFB1C5', '#C6C6C6']
on_variant_2 = ['#690004', '#512400', '#3B2F00', '#1F3700', '#253600', '#003737', '#181F89', '#00344F', '#500075',
'#5C005A', '#5E1130', '#303030']
# VARIANT 3 ----------------------------------------------------------------
variant_3 = ['#FFDAD5', '#FFDBC7', '#FFE177', '#ACF850', '#CAF07D', '#6FF6F7', '#E0E0FF', '#CAE6FF', '#F6D9FF',
'#FFD7F4', '#FFD9E1', '#E2E2E2']
on_variant_3 = ['#410001', '#311300', '#231B00', '#102000', '#141F00', '#002020', '#00036B', '#001E30', '#310049',
'#380037', '#3F001B', '#1B1B1B']
@app.route('/')
def home():
return 'You can go to <a href="/badge/stars/2/2/arsho/Hackerrank_Python_Domain_Solutions">/badge/stars/2/2/arsho/Hackerrank_Python_Domain_Solutions</a> to see the stars for arsho/Hackerrank_Python_Domain_Solutions repository'
@app.route('/badge/stars/<style>/<variant>/<username>/<repo>')
def github_stars_badge(style, variant, username, repo):
url = f'https://api.github.com/repos/{username}/{repo}'
headers = {'Accept': 'application/vnd.github.v3+json'}
r = requests.get(url, headers=headers)
if r.ok:
index = int(style) - 1
if variant == '1':
background = variant_1[index]
foreground = on_variant_1
if variant == '2':
background = variant_2[index]
foreground = on_variant_2[index]
if variant == '3':
background = variant_3[index]
foreground = on_variant_3[index]
data = r.json()
stars = data['stargazers_count']
if len(str(stars)) == 1:
width = 20 + 68
elif len(str(stars)) == 2:
width = 2 * 16 + 68
elif len(str(stars)) == 3:
width = 3 * 14 + 68
elif len(str(stars)) == 4:
width = 4 * 13 + 68
else:
width = len(str(stars)) * 13 + 68
svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="30" fill="{background}" rx="15"><path d="M40 0h4v20h-4z" fill="#4c1"/><rect rx="15" width="{width}" height="30" fill="{background}"/><text x="11" y="22" fill="{foreground}" font-size="20" font-family="Product Sans">Stars : {stars}</text></svg>'
return Response(svg, mimetype='image/svg+xml')
else:
return 'Error', r.status_code
Screenshot:
Upvotes: 0
Reputation: 159
Directory Structure of dynamicBadges
:
.
├── main.py
├── requirements.txt
└── vercel.json
The first fix is with the requirements.txt. requests
is not part of the Python Standard Library and hence must be included. The requirements.txt should look like:
blinker==1.6.2
certifi==2023.5.7
charset-normalizer==3.1.0
click==8.1.3
colorama==0.4.6
Flask==2.3.2
idna==3.4
importlib-metadata==6.7.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
requests==2.31.0
urllib3==2.0.3
Werkzeug==2.3.6
zipp==3.15.0
The second fix is with the vercel.json configuration. Use the following configuration:
{
"version": 2,
"builds": [
{
"src": "main.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "(.*)",
"dest": "main.py"
}
]}
Link to Sample Deployment: https://badges-vercel.vercel.app/badge/stars/1/1/microsoft/vscode
Upvotes: 1