Python 30行代码实现短链服务

421 阅读2分钟

相关依赖

  • Python3
  • Flask
  • MySQL

创建文件flask_short_link.py,整个应用只有这一个文件,去除空格代码在30行左右。

应用配置

导入相关依赖。

# 导入所需的模块
import random
import re
from datetime import datetime

from flask import Flask
from flask import request, abort, redirect
from flask_sqlalchemy import SQLAlchemy

定义配置,实例化应用对象以及数据库对象。

# 配置
class AppConfig:
    SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:root@localhost/test"
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_ECHO = True
    
# 实例化Flask和数据库对象
app = Flask(__name__)
app.config.from_object(AppConfig())
db = SQLAlchemy(app)
  • SQLALCHEMY_DATABASE_URI 是flask的数据库连接,注意这里换成你自己的配置。
  • SQLALCHEMY_TRACK_MODIFICATIONS 如果设置成 True (默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存, 如果不必要的可以禁用它。
  • SQLALCHEMY_ECHO 如果设置成 True,SQLAlchemy 将会记录所有 发到标准输出(stderr)的语句,这对调试很有帮助。
  • 最后实例化Flas 对象和数据库对象,后面会使用到。

创建模型和数据库映射

# model
class ShortLink(db.Model):
    __tablename__ = 'tb_short_link'

    id = db.Column(db.Integer, primary_key=True)
    short_key = db.Column(db.String(30), unique=True, nullable=False) # 短连接KEY,数据库唯一
    source_url = db.Column(db.String(300), nullable=False)			  # 原连接
    created_time = db.Column(db.DateTime, nullable=False)
  • ShortLink 作为短连模型,指定和数据库映射的表名称为 tb_short_link。
  • 更多可参考flask-sqlalchemy官方文档:www.pythondoc.com/flask-sqlal…

生成短连接口

@app.route("/short-link/create", methods=['POST', 'GET'])
def create_short_link():
    """创建短连接"""
    SOURCE_KEYS = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
                   'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
                   '6', '7', '8', '9']
    url = request.args.get('url')
    if not url or not re.match(r'^https?:/{2}\w.+$', url):
        return {'success': False, 'message': '参数url不合法'}
    short_key = ''.join(random.sample(SOURCE_KEYS, 8))  # 数据库建了唯一索引,若重复提醒用户重试
    sl = ShortLink(short_key=short_key, source_url=url, created_time=datetime.now())
    db.session.add(sl)
    db.session.commit()
    short_full_url = 'http://localhost:9091/' + short_key  # 线上更换成短连接域名
    return {"id": sl.id, "short_full_url": short_full_url,
            'created_time': sl.created_time.strftime('%Y-%m-%d %H:%M:%S')}
  • 生成原理目前很简陋,仅做参考,定义一个包含所有字母和数据的集合,每次创建短连接从集合中随机取8位作为KEY,再和原链接关联,存入到数据库,这里暂不考虑碰撞和性能。
  • 值得注意的是目前的做法每个相同的URL每次都会生成不同的短连接,如果你需要保证原链接唯一,可以对原链接取md5值后存储,当收到新的短连接请求后可用于判断是否已存在,如果存在直接返回已存在的短连接即可。
  • 更加高效的可用python提供的hash库等组件实现。

根据短连重定向到原链接

@app.route("/<string:short_key>", methods=['GET'])
def redirect_source_url(short_key):
    """传入短连后重定向到到原链接"""
    sl = ShortLink.query.filter_by(short_key=short_key).first()
    return redirect(sl.source_url) if sl else abort(404)
  • 根据用户传入的短连key从数据库查到原地址,再使用flask提供的重定向函数redirect重定向到原地址。

启动应用

首先创建数据库表,有两种方式: ​

一种是根据Model自动生成表。

# 在python控制台下执行
>>> from flask_short_link import db
>>> db.create_all()

另一种:在数据库客户端执行如下SQL脚本。

CREATE TABLE `tb_short_link` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `short_key` varchar(30) NOT NULL,
  `source_url` varchar(300) NOT NULL,
  `created_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `short_key` (`short_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

再调用app的run方法启动应用,设置端口为9091, 开启debug方便观察输出信息。

if __name__ == '__main__':
    app.run(port=9091, debug=True)

控制台有如下输出说明启动成功。

Connected to pydev debugger (build 211.7142.45)
 * Serving Flask app 'flask_short_link' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:9091/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 771-475-169

测试

为百度首页生成一个短连接作为测试。

mac:~ $ x-tools request http://127.0.0.1:9091/short-link/create?url=http://www.baidu.com

# 输出如下信息
{
  "created_time": "2022-01-25 16:56:48",
  "id": 78,
  "short_full_url": "http://localhost:9091/f6rimes5"
}

  • short_full_url 为短连接地址,后面的字符串为短连接KEY。

打开浏览器访问 http://localhost:9091/f6rimes5,重定向到百度,搞定!

查看数据库,如下是我测试生成的数据。 image.png

完整flask_short_link.py文件

github.com/telzhou618/…

x-tools 工具也可以用 curl 代替,感兴趣的朋友可以点击下面链接获取更多信息!

github.com/telzhou618/…