{"id":34103952,"url":"https://github.com/tcantalice/tinyrouter","last_synced_at":"2026-04-24T14:33:21.399Z","repository":{"id":53645592,"uuid":"235114020","full_name":"tcantalice/tinyrouter","owner":"tcantalice","description":null,"archived":false,"fork":false,"pushed_at":"2021-03-20T02:51:54.000Z","size":45,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-20T19:52:40.668Z","etag":null,"topics":["flask","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tcantalice.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-01-20T13:59:26.000Z","updated_at":"2020-02-16T14:41:20.000Z","dependencies_parsed_at":"2022-09-26T17:00:25.761Z","dependency_job_id":null,"html_url":"https://github.com/tcantalice/tinyrouter","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/tcantalice/tinyrouter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcantalice%2Ftinyrouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcantalice%2Ftinyrouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcantalice%2Ftinyrouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcantalice%2Ftinyrouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tcantalice","download_url":"https://codeload.github.com/tcantalice/tinyrouter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcantalice%2Ftinyrouter/sbom","scorecard":{"id":870447,"data":{"date":"2025-08-11","repo":{"name":"github.com/tcantalice/tinyrouter","commit":"1dcefc6c29aabede8a569c024d103c568ae2069b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/23 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-24T04:02:57.481Z","repository_id":53645592,"created_at":"2025-08-24T04:02:57.481Z","updated_at":"2025-08-24T04:02:57.481Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27733048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-14T02:00:11.348Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","python"],"created_at":"2025-12-14T17:56:28.371Z","updated_at":"2025-12-14T17:56:28.954Z","avatar_url":"https://github.com/tcantalice.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tiny Router\nTiny Router é um roteador de caminhos para aplicações [Flask](https://github.com/pallets/flask). A biblioteca centraliza a definição e gerenciamento das rotas utilizadas na aplicação, criar, editar, remover ou trocar controladores facilmente evitando conflitos.\n\n- [Criando rotas](#criando-rotas)\n- [Registrando rotas](#registrando-rotas)\n- [Funções Helper](#funções-helper)\n    - [Métodos HTTP](#métodos-http)\n    - [Préfixos](#préfixos)\n- [Dicas de uso](#dicas-de-uso)\n\n## Criando rotas\n\nUma rota é representada pela classe ```Route```. Ela possui os seguinte atributos:\n\n* **endpoint** - Nome utilizado para identificar a rota. Em caso de endpoints com múltiplos termos, recomendado separá-los por ponto ou sublinhado.\n* **rule** - Caminho para um recurso específico\n* **view** - Função ou classe que irá manipular a requisição\n* **methods** - Métodos HTTP para chamada da rota (Default: ```{'GET'}```)\n* **parameters** - Parâmetros que podem ser passados na url.\n\nAo criar uma rota apenas são obrigatórios ```endpoint```, ```rule``` e ```view```.\n\nExemplo de uma rota simples:\n```python\nfrom tinyrouter import Route\nfrom views import user_index\n\nRoute('user.index', '/user', user_index)\n```\nPor padrão, as rotas são definidas para aceitas apenas o método ```GET```. Entretanto outros métodos podem ser definidos, ou até mais de um.\n```python\nfrom tinyrouter import Route\nfrom views import user_index\n\n# Definição dos métodos\nmethods = ['GET', 'POST']\n\nRoute('user.index', '/user', user_index, methods)\n```\n## Registrando as rotas\n\nPrimeiro cria-se uma instância do roteador\n```python\nfrom flask import Flask\nfrom tinyrouter import Router\n\napp = Flask(__name__)\nrouter = Router(app)\n```\n\nE invoca o método ```register``` passando a lista de rotas que deseja registrar na aplicação\n```python\n'''\nImportaçãoes anteriores\n'''\nfrom my_app.routes import routes\n\n'''\n Instância da aplicação e do roteador\n'''\nrouter.register(routes)\n```\n\nPronto! As rotas agora estão registradas na aplicação.\n\nÉ possível registrar vários grupos de rotas.\n```python\nfrom webapp.routes import routes as web_routes\nfrom api.routes import routes as api_routes\n\nrouter.register(web_routes)\nrouter.register(api_routes)\n```\nOu ainda...\n```python\nrouter.register(web_routes, api_routes)\n```\n\n## Funções Helper\n### **Métodos HTTP**\nCriar uma rota que aceite apenas uma método HTTP utilizando Route fica da seguinte forma:\n```python\n# Importação da view...\nfrom tinyrouter import Route\n\n\nRoute('cliente.create', '/cliente', cliente_create, ['POST'])\n```\nEntretanto esse processo pode ser encurtado com os helpers de métodos.\nUtilizando os helpers, o exemplo acima ficaria assim:\n```python\n# Importação da view...\nfrom tinyrouter.helpers import route_post as post\n\npost('cliente.create', '/cliente', cliente_create)\n```\nO resultado será exatamente o mesmo. Os métodos suportados são:\n- GET\n- POST\n- PUT\n- DELETE\n\n\n### **Préfixos**\nAgrupar rotas de acordo com o recurso ou contexto utilizando o Route pode ser um pouco verboso, como por exemplo, rotas associadas ao recurso Cliente.\n\n**[GET] - /cliente/** (Lista todos os Clientes)\u003cbr\u003e\n**[POST] - /cliente/** (Cria um novo registro de Cliente)\u003cbr\u003e\n**[GET] - /cliente/{id}** (Recupera um registro específico de Cliente)\u003cbr\u003e\n**[PUT] - /cliente/{id}** (Atualiza um registro específico de Cliente)\u003cbr\u003e\n**[DELETE] - /cliente/{id}** (Deleta um registro específico de Cliente )\n\nÉ possível notar que para cada um dos endpoints foi necessário pôr o nome do recurso (Cliente) como préfixo. Utilizando o helper de préfixo esse trabalho não será mais necessário. A função recebe o préfixo a ser adicionado e as rotas que receberão o mesmo. Exemplo:\n\n```python\n# Importação das views\nfrom tinyrouter.helpers import route_prefix as prefix\nfrom tinyrouter.helpers import (route_get as get,\\\n                                route_post as post,\\\n                                route_put as put,\\\n                                route_delete as delete)\n\n*prefix('cliente', \n        get('cliente.all', '/', cliente_all),\n        post('cliente.create', '/', cliente_create),\n        put('cliente.udpate', '/\u003cid\u003e', cliente_update),\n        get('cliente.show'), '/\u003cid\u003e', cliente_show),\n        delete('cliente.delete', '/\u003cid\u003e', cliente_delete)\n    )\n```\nNOTA: *Ao utilizar o route_prefix é necessário pôr um * na frente da função pois é retornado uma coleção de rotas alteradas, e este artifício garante que as rotas serão \"desempacotadas\". Entretanto não impede que as novas rotas sejam armazenadas em uma variável.*\n\nÉ possível também utilizar aninhamentos do ```route_prefix```\n```python\n# Importações...\n\n*prefix('sistema', \n    *prefix('cliente',\n        ...\n    )\n)\n```\nCom isso é possível agrupar diversos contextos com um mesmo préfixo sem a necessidade de definir por extenso um a um.\n\n## Dicas de Uso\n1. Utilizar um arquivo de rotas para cada parte da aplicação. Exemplo:\n```python\n# ./clientes/routes.py\nfrom tinyrouter import Route\nfrom .views\n\nroutes = [\n    *route_prefix('/cliente',\n        Route('cliente.index', '/', views.index),\n        Route('cliente.show', '/\u003cint:id\u003e', views.show),\n        Route('cliente.create', '/create', views.create, ['GET', 'POST'])\n    )\n]\n```\n```python\n# ./app.py\nfrom flask import Flask\nfrom tinyrouter import Router\nfrom clientes.routes import routes as rotas_clientes\n\napp = Flask(__name__)\nrouter = Router(app)\nrouter.register(rotas_clientes)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftcantalice%2Ftinyrouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftcantalice%2Ftinyrouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftcantalice%2Ftinyrouter/lists"}