├── agate-script ├── .gitignore ├── agate.db ├── admin │ ├── data │ │ └── agate.db │ └── config │ │ └── application-install.properties ├── agate-install.bat ├── agate-install.sh ├── gateway │ └── config │ │ └── config.json ├── docker-compose.yml └── agate.sqlite.sql ├── .gitignore ├── agate-admin ├── .gitignore ├── src │ └── main │ │ ├── resources │ │ ├── static │ │ │ ├── assets │ │ │ │ ├── avatar-c2859f91.js │ │ │ │ ├── Write-e62d3f5d.css │ │ │ │ ├── Show-c23b4a19.css │ │ │ │ ├── useIcon-f4304df6.js │ │ │ │ ├── avatar-3332c51e.jpg │ │ │ │ ├── logo-bd01a334.png │ │ │ │ ├── LocaleDropdown-8fa91b01.css │ │ │ │ ├── tsxHelper-11a4c46e.js │ │ │ │ ├── Detail-67ad6a73.js │ │ │ │ ├── Detail-876a21f0.js │ │ │ │ ├── Detail-ca28ad8d.js │ │ │ │ ├── index-219675da.js │ │ │ │ ├── apps-b1fd5c88.js │ │ │ │ ├── Login-5f5fdf72.css │ │ │ │ ├── Write-06dd84a7.js │ │ │ │ ├── Write-bca44a6e.js │ │ │ │ ├── RegisterForm-1fc02880.js │ │ │ │ ├── 404-76e21df1.js │ │ │ │ ├── route-9803be03.js │ │ │ │ ├── 403-1f407cb2.js │ │ │ │ ├── 500-e2841507.js │ │ │ │ ├── Detail.vue_vue_type_script_setup_true_lang-0380e26c.js │ │ │ │ ├── Detail.vue_vue_type_script_setup_true_lang-a83c6255.js │ │ │ │ ├── Write-0589aed0.js │ │ │ │ ├── LoginForm-648e57db.js │ │ │ │ ├── gateway-29ace984.js │ │ │ │ ├── useEmitt-76f9af94.js │ │ │ │ ├── Redirect-35e11f5c.js │ │ │ │ ├── useValidator-0a43379b.js │ │ │ │ ├── ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js │ │ │ │ ├── Write.vue_vue_type_script_setup_true_lang-5ad32267.js │ │ │ │ ├── Write.vue_vue_type_script_setup_true_lang-c8502536.js │ │ │ │ ├── Detail.vue_vue_type_script_setup_true_lang-61edcffb.js │ │ │ │ ├── Detail-da843398.js │ │ │ │ ├── el-card-48e750da.css │ │ │ │ ├── Detail-0bfbc759.js │ │ │ │ ├── Error.vue_vue_type_script_setup_true_lang-bc8e476e.js │ │ │ │ ├── Add-978396b6.js │ │ │ │ ├── Add-27afb4b3.js │ │ │ │ ├── Edit-321cbe46.js │ │ │ │ ├── useCrudSchemas-2c80f3ed.js │ │ │ │ ├── Edit-94a229f6.js │ │ │ │ ├── Write.vue_vue_type_script_setup_true_lang-c9eb325e.js │ │ │ │ ├── Workplace-1be4c26c.css │ │ │ │ ├── Descriptions-e6f4f0ea.js │ │ │ │ ├── el-popper-cecd0dcb.css │ │ │ │ ├── LocaleDropdown.vue_vue_type_script_setup_true_lang-f77fc5b1.js │ │ │ │ ├── RegisterForm.vue_vue_type_script_setup_true_lang-73f185cd.js │ │ │ │ ├── tree-91585a69.js │ │ │ │ ├── Login-3cc6bcdf.js │ │ │ │ └── el-link-0543119b.css │ │ │ ├── logo.png │ │ │ └── favicon.ico │ │ ├── application.properties │ │ ├── application-develop.properties │ │ ├── application-release.properties │ │ └── log4j2.xml │ │ └── java │ │ └── io │ │ └── agate │ │ └── admin │ │ ├── business │ │ ├── model │ │ │ ├── ParamType.java │ │ │ ├── PluginDefinition.java │ │ │ ├── FrontendDefinition.java │ │ │ ├── ParamDefinition.java │ │ │ ├── AppDefinition.java │ │ │ ├── ClusterDefinition.java │ │ │ ├── UserDefinition.java │ │ │ ├── InstanceDefinition.java │ │ │ ├── GatewayDefinition.java │ │ │ └── RouteDefinition.java │ │ ├── port │ │ │ ├── AccountRepository.java │ │ │ ├── CatalogRepository.java │ │ │ ├── AppRepository.java │ │ │ ├── ClusterRepository.java │ │ │ ├── GatewayRepository.java │ │ │ └── RouteRepository.java │ │ ├── param │ │ │ ├── GatewayQuery.java │ │ │ ├── RouteQuery.java │ │ │ ├── PageQuery.java │ │ │ ├── PageList.java │ │ │ └── AppDetail.java │ │ ├── BusinessException.java │ │ └── service │ │ │ └── AuthenService.java │ │ ├── store │ │ ├── EmptyCatalogRepository.java │ │ └── ConsulCatalogRepository.java │ │ ├── repository │ │ ├── AccountRepositoryDao.java │ │ └── entity │ │ │ ├── ClusterEntity.java │ │ │ ├── AppEntity.java │ │ │ ├── GatewayEntity.java │ │ │ └── RouteEntity.java │ │ ├── security │ │ └── WebSecurityConfigurer.java │ │ ├── api │ │ ├── AuthenResource.java │ │ ├── ClusterResource.java │ │ ├── AppsResource.java │ │ ├── RouteResource.java │ │ └── GatewayResource.java │ │ └── AgateAdminListener.java └── Dockerfile ├── agate-gateway ├── .gitignore ├── Dockerfile └── src │ ├── main │ ├── resources │ │ ├── config.json │ │ └── log4j2.xml │ └── java │ │ └── io │ │ └── agate │ │ └── gateway │ │ ├── options │ │ └── ParamType.java │ │ ├── service │ │ ├── Loadbalancer.java │ │ ├── ServiceAddress.java │ │ ├── ServiceAddressSupplier.java │ │ ├── DefaultServiceAddress.java │ │ ├── FixedServiceAddressSupplier.java │ │ ├── RandomLoadBalancer.java │ │ └── RoundRobinLoadBalancer.java │ │ ├── context │ │ ├── ContextConstants.java │ │ ├── AddressConstant.java │ │ └── AgateVerticleFactory.java │ │ ├── handler │ │ ├── RouteHandler.java │ │ ├── internal │ │ │ ├── ZipkinTracingHandler.java │ │ │ ├── RestfulFailureHandler.java │ │ │ ├── RateLimitHandler.java │ │ │ ├── MeterMetricsHandler.java │ │ │ └── ProxyReplyHandler.java │ │ └── OrderedHandler.java │ │ ├── plugin │ │ ├── RouteHandlerPlugin.java │ │ ├── internal │ │ │ ├── AccessLogPlugin.java │ │ │ ├── ProxyReplyPlugin.java │ │ │ ├── MeterMetricsPlugin.java │ │ │ ├── RateLimitPlugin.java │ │ │ ├── ZipkinTracingPlugin.java │ │ │ ├── CircuitBreakerPlugin.java │ │ │ ├── RestfulFailurePlugin.java │ │ │ └── HttpProxyPlugin.java │ │ └── PluginOptions.java │ │ ├── http │ │ ├── HttpUtil.java │ │ ├── QueryCoder.java │ │ └── RestfulUtil.java │ │ ├── deploy │ │ └── ClusterDeploy.java │ │ ├── verticle │ │ └── SystemVerticle.java │ │ └── utils │ │ └── ConfigUtil.java │ └── test │ ├── resources │ ├── config2.json │ ├── config.json │ └── log4j2.xml │ └── java │ └── io │ └── agate │ └── gateway │ ├── CarType.java │ ├── AgateGatewayLauncherTest.java │ ├── AgateGatewayLauncherTest3.java │ ├── OrderedTest.java │ ├── AgateGatewayLauncherTest2.java │ ├── TimeSlot.java │ ├── http │ ├── HttpClientTest.java │ └── QueryCoderTest.java │ ├── DateFormatTest.java │ ├── RedisTest.java │ └── Trie.java ├── license-header └── ApacheV2.txt └── README.md /agate-script/.gitignore: -------------------------------------------------------------------------------- 1 | /consul/ 2 | /admin/logs/ 3 | /gateway/logs/ 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.settings/ 2 | /.project 3 | /agate.iml 4 | /.idea/ 5 | /logs/ 6 | -------------------------------------------------------------------------------- /agate-admin/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings/ 2 | /logs/ 3 | /target/ 4 | /.classpath 5 | /.project 6 | -------------------------------------------------------------------------------- /agate-script/agate.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinstone/agate/HEAD/agate-script/agate.db -------------------------------------------------------------------------------- /agate-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.classpath 3 | /.project 4 | /.settings/ 5 | /logs/ 6 | /agate-gateway.iml 7 | -------------------------------------------------------------------------------- /agate-script/admin/data/agate.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinstone/agate/HEAD/agate-script/admin/data/agate.db -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/avatar-c2859f91.js: -------------------------------------------------------------------------------- 1 | const a="/assets/avatar-3332c51e.jpg";export{a as _}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Write-e62d3f5d.css: -------------------------------------------------------------------------------- 1 | .el-col-first[data-v-10ee44bc]{margin-left:20px;border-radius:4px} 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinstone/agate/HEAD/agate-admin/src/main/resources/static/logo.png -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinstone/agate/HEAD/agate-admin/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Show-c23b4a19.css: -------------------------------------------------------------------------------- 1 | .el-col-first[data-v-b67d89d9]{margin-left:20px;margin-right:-20px;border-radius:4px} 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/useIcon-f4304df6.js: -------------------------------------------------------------------------------- 1 | import{aZ as a,a2 as s}from"./index-5b8751dc.js";const o=o=>a(s,o);export{o as u}; 2 | -------------------------------------------------------------------------------- /agate-script/agate-install.bat: -------------------------------------------------------------------------------- 1 | docker compose stop 2 | echo y | docker compose rm 3 | 4 | cd .. 5 | mvn clean install 6 | 7 | cd agate-script 8 | docker compose up -d -------------------------------------------------------------------------------- /agate-script/agate-install.sh: -------------------------------------------------------------------------------- 1 | docker compose stop 2 | echo y | docker compose rm 3 | 4 | cd .. 5 | mvn clean install 6 | 7 | cd agate-script 8 | docker compose up -d -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/avatar-3332c51e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinstone/agate/HEAD/agate-admin/src/main/resources/static/assets/avatar-3332c51e.jpg -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/logo-bd01a334.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinstone/agate/HEAD/agate-admin/src/main/resources/static/assets/logo-bd01a334.png -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/LocaleDropdown-8fa91b01.css: -------------------------------------------------------------------------------- 1 | [data-v-e70fc6a8]:export{namespace:v;elNamespace:el}[data-v-e70fc6a8] .el-switch__core .el-switch__inner .is-icon{overflow:visible} 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/tsxHelper-11a4c46e.js: -------------------------------------------------------------------------------- 1 | import{br as r}from"./index-5b8751dc.js";const n=(n,t="default",e)=>{if(!n||!Reflect.has(n,t))return null;if(!r(n[t]))return null;const l=n[t];return l?l(e):null};export{n as g}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail-67ad6a73.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./Detail.vue_vue_type_script_setup_true_lang-a83c6255.js";import"./Descriptions-e6f4f0ea.js";import"./index-5b8751dc.js";/* empty css */export{e as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail-876a21f0.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./Detail.vue_vue_type_script_setup_true_lang-0380e26c.js";import"./Descriptions-e6f4f0ea.js";import"./index-5b8751dc.js";/* empty css */export{e as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail-ca28ad8d.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./Detail.vue_vue_type_script_setup_true_lang-61edcffb.js";import"./Descriptions-e6f4f0ea.js";import"./index-5b8751dc.js";/* empty css */export{e as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=agate-admin 2 | 3 | # active profile 4 | spring.profiles.active=develop 5 | 6 | # server info 7 | server.port=8888 8 | 9 | # error info 10 | server.error.include-message=always 11 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/index-219675da.js: -------------------------------------------------------------------------------- 1 | import{r as a}from"./index-e446de42.js";const t=t=>a.post({url:"/authen/login",data:t}),r=()=>a.put({url:"/authen/logout"}),s=t=>a.get({url:"/role/list",params:t}),l=t=>a.get({url:"/role/list2",params:t});export{l as a,r as b,s as g,t as l}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/apps-b1fd5c88.js: -------------------------------------------------------------------------------- 1 | import{r as a}from"./index-e446de42.js";const s=s=>a.get({url:"/apps/list",params:s}),p=s=>a.get({url:"/apps/detail",params:s}),e=s=>a.post({url:"/apps/save",data:s}),t=s=>a.delete({url:"/apps/delete",data:s});export{p as a,t as d,s as g,e as s}; 2 | -------------------------------------------------------------------------------- /agate-gateway/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:19-jdk-alpine 2 | ARG JAR_FILE 3 | ENV CONFIG_FILE="/agate-gateway/config/config.json" 4 | VOLUME /agate-gateway/config 5 | VOLUME /agate-gateway/logs 6 | ADD target/${JAR_FILE} /agate-gateway/gateway-fat.jar 7 | WORKDIR /agate-gateway/ 8 | ENTRYPOINT java -Dconfig.file=$CONFIG_FILE -jar gateway-fat.jar -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Login-5f5fdf72.css: -------------------------------------------------------------------------------- 1 | [data-v-78683172]:export{namespace:v;elNamespace:el}.v-login[data-v-78683172]{overflow:auto}.v-login__left[data-v-78683172]:before{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;background-image:url(/assets/login-bg-e36b8ca7.svg);background-position:center;background-repeat:no-repeat;content:""} 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Write-06dd84a7.js: -------------------------------------------------------------------------------- 1 | import{_ as t}from"./Write.vue_vue_type_script_setup_true_lang-5ad32267.js";import"./useForm-95be4c91.js";import"./index-5b8751dc.js";/* empty css */import"./tsxHelper-11a4c46e.js";/* empty css *//* empty css */import"./useValidator-0a43379b.js";export{t as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Write-bca44a6e.js: -------------------------------------------------------------------------------- 1 | import{_ as t}from"./Write.vue_vue_type_script_setup_true_lang-c8502536.js";import"./useForm-95be4c91.js";import"./index-5b8751dc.js";/* empty css */import"./tsxHelper-11a4c46e.js";/* empty css *//* empty css */import"./useValidator-0a43379b.js";export{t as default}; 2 | -------------------------------------------------------------------------------- /agate-script/gateway/config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "gateway": { 3 | "cluster": "product" 4 | }, 5 | "vertx": { 6 | "workerPoolSize": 4, 7 | "eventLoopPoolSize": 2, 8 | "blockedThreadCheckInterval": 1000 9 | }, 10 | "verticle": { 11 | "manage.instances": 1, 12 | "system.instances": 1 13 | }, 14 | "consul": { 15 | "host": "agate-consul", 16 | "port": 8500 17 | } 18 | } -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/RegisterForm-1fc02880.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./RegisterForm.vue_vue_type_script_setup_true_lang-73f185cd.js";import"./useForm-95be4c91.js";import"./index-5b8751dc.js";/* empty css */import"./tsxHelper-11a4c46e.js";/* empty css *//* empty css */import"./useValidator-0a43379b.js";export{e as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:19-jdk-alpine 2 | ARG JAR_FILE 3 | ENV APP_NAME=agate-admin 4 | ENV ACTIVE_PROFILE="release" 5 | VOLUME /agate-admin/logs 6 | VOLUME /agate-admin/data 7 | VOLUME /agate-admin/config 8 | ADD target/${JAR_FILE} /agate-admin/admin-fat.jar 9 | WORKDIR /agate-admin/ 10 | ENTRYPOINT java -cp /agate-admin/config -Dspring.profiles.active=$ACTIVE_PROFILE -jar admin-fat.jar -------------------------------------------------------------------------------- /agate-gateway/src/main/resources/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "gateway": { 3 | "cluster": "product" 4 | }, 5 | "vertx": { 6 | "workerPoolSize": 4, 7 | "eventLoopPoolSize": 4, 8 | "blockedThreadCheckInterval": 1000 9 | }, 10 | "verticle": { 11 | "manage.instances": 1, 12 | "system.instances": 1 13 | }, 14 | "consul": { 15 | "host": "192.168.1.120", 16 | "port": 8500 17 | } 18 | } -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/404-76e21df1.js: -------------------------------------------------------------------------------- 1 | import{_ as r}from"./Error.vue_vue_type_script_setup_true_lang-bc8e476e.js";import{d as s,u as t,m as a,o,i as e,a as u}from"./index-5b8751dc.js";/* empty css */const p=s({__name:"404",setup(s){const{push:p}=t(),n=a(),_=()=>{var r;p(null==(r=n.addRouters[0])?void 0:r.path)};return(s,t)=>(o(),e(u(r),{onErrorClick:_}))}});export{p as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/route-9803be03.js: -------------------------------------------------------------------------------- 1 | import{r as a}from"./index-e446de42.js";const t=t=>a.get({url:"/route/list",params:t}),r=t=>a.get({url:"/route/detail",params:{id:t}}),e=t=>a.post({url:"/route/save",data:t}),s=t=>a.delete({url:"/route/delete",data:t}),u=t=>a.put({url:"/route/start",params:{id:t}}),o=t=>a.put({url:"/route/close",params:{id:t}});export{e as a,r as b,o as c,s as d,t as g,u as s}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/403-1f407cb2.js: -------------------------------------------------------------------------------- 1 | import{_ as r}from"./Error.vue_vue_type_script_setup_true_lang-bc8e476e.js";import{d as s,u as t,m as a,o,i as e,a as u}from"./index-5b8751dc.js";/* empty css */const p=s({__name:"403",setup(s){const{push:p}=t(),n=a(),_=()=>{var r;p(null==(r=n.addRouters[0])?void 0:r.path)};return(s,t)=>(o(),e(u(r),{type:"403",onErrorClick:_}))}});export{p as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/500-e2841507.js: -------------------------------------------------------------------------------- 1 | import{_ as r}from"./Error.vue_vue_type_script_setup_true_lang-bc8e476e.js";import{d as s,u as t,m as a,o,i as e,a as u}from"./index-5b8751dc.js";/* empty css */const p=s({__name:"500",setup(s){const{push:p}=t(),n=a(),_=()=>{var r;p(null==(r=n.addRouters[0])?void 0:r.path)};return(s,t)=>(o(),e(u(r),{type:"500",onErrorClick:_}))}});export{p as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail.vue_vue_type_script_setup_true_lang-0380e26c.js: -------------------------------------------------------------------------------- 1 | import{D as a}from"./Descriptions-e6f4f0ea.js";import{d as e,o as t,i as s,a as r}from"./index-5b8751dc.js";const o=e({__name:"Detail",props:{currentRow:{type:Object,default:()=>null},detailSchema:{type:Array,default:()=>[]}},setup:e=>(o,c)=>(t(),s(r(a),{schema:e.detailSchema,data:e.currentRow||{}},null,8,["schema","data"]))});export{o as _}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail.vue_vue_type_script_setup_true_lang-a83c6255.js: -------------------------------------------------------------------------------- 1 | import{D as a}from"./Descriptions-e6f4f0ea.js";import{d as e,o as t,i as s,a as r}from"./index-5b8751dc.js";const o=e({__name:"Detail",props:{currentRow:{type:Object,default:()=>null},detailSchema:{type:Array,default:()=>[]}},setup:e=>(o,c)=>(t(),s(r(a),{schema:e.detailSchema,data:e.currentRow||{}},null,8,["schema","data"]))});export{o as _}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Write-0589aed0.js: -------------------------------------------------------------------------------- 1 | import{_ as t}from"./Write.vue_vue_type_script_setup_true_lang-c9eb325e.js";import"./useForm-95be4c91.js";import"./index-5b8751dc.js";/* empty css */import"./tsxHelper-11a4c46e.js";/* empty css *//* empty css */import"./useValidator-0a43379b.js";import"./gateway-29ace984.js";import"./index-e446de42.js";export{t as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/LoginForm-648e57db.js: -------------------------------------------------------------------------------- 1 | import{_ as r}from"./LoginForm.vue_vue_type_script_setup_true_lang-d1c06f36.js";import"./useForm-95be4c91.js";import"./index-5b8751dc.js";/* empty css */import"./tsxHelper-11a4c46e.js";/* empty css *//* empty css *//* empty css */import"./index-219675da.js";import"./index-e446de42.js";import"./useValidator-0a43379b.js";export{r as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/gateway-29ace984.js: -------------------------------------------------------------------------------- 1 | import{r as a}from"./index-e446de42.js";const t=()=>a.get({url:"/cluster/list"}),e=t=>a.get({url:"/gateway/list",params:t}),s=t=>a.get({url:"/gateway/detail",params:{id:t}}),r=t=>a.post({url:"/gateway/save",data:t}),l=t=>a.delete({url:"/gateway/delete",data:t}),d=t=>a.put({url:"/gateway/start",params:{id:t}}),g=t=>a.put({url:"/gateway/close",params:{id:t}});export{e as a,r as b,g as c,l as d,s as e,t as g,d as s}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/useEmitt-76f9af94.js: -------------------------------------------------------------------------------- 1 | import{ah as n}from"./index-5b8751dc.js";const e={all:t=t||new Map,on:function(n,e){var a=t.get(n);a?a.push(e):t.set(n,[e])},off:function(n,e){var a=t.get(n);a&&(e?a.splice(a.indexOf(e)>>>0,1):t.set(n,[]))},emit:function(n,e){var a=t.get(n);a&&a.slice().map((function(n){n(e)})),(a=t.get("*"))&&a.slice().map((function(t){t(n,e)}))}};var t;const a=t=>(t&&(e.on(t.name,t.callback),n((()=>{e.off(t.name)}))),{emitter:e});export{a as u}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Redirect-35e11f5c.js: -------------------------------------------------------------------------------- 1 | import{d as e,u as t,a as r,o as a,c as s}from"./index-5b8751dc.js";const p=e({__name:"Redirect",setup(e){const{currentRoute:p,replace:c}=t(),{params:o,query:n}=r(p),{path:d,_redirect_type:i="path"}=o;Reflect.deleteProperty(o,"_redirect_type"),Reflect.deleteProperty(o,"path");const u=Array.isArray(d)?d.join("/"):d;return c("name"===i?{name:u,query:n,params:o}:{path:u.startsWith("/")?u:"/"+u,query:n}),(e,t)=>(a(),s("div"))}});export{p as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/useValidator-0a43379b.js: -------------------------------------------------------------------------------- 1 | import{k as e}from"./index-5b8751dc.js";const{t:n}=e(),r=()=>({required:e=>({required:!0,message:e||n("common.required")}),lengthRange:e=>{const{min:r,max:a,message:o}=e;return{min:r,max:a,message:o||n("common.lengthRange",{min:r,max:a})}},notSpace:e=>({validator:(r,a,o)=>{-1!==(null==a?void 0:a.indexOf(" "))?o(new Error(e||n("common.notSpace"))):o()}}),notSpecialCharacters:e=>({validator:(r,a,o)=>{/[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/gi.test(a)?o(new Error(e||n("common.notSpecialCharacters"))):o()}})});export{r as u}; 2 | -------------------------------------------------------------------------------- /license-header/ApacheV2.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) ${year} ${owner}<${email}> 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /agate-script/admin/config/application-install.properties: -------------------------------------------------------------------------------- 1 | 2 | #jdbc datasource 3 | spring.datasource.url=jdbc:sqlite:data/agate.db 4 | spring.datasource.driver-class-name=org.sqlite.JDBC 5 | spring.datasource.username=root 6 | spring.datasource.password=123456 7 | 8 | # datasource connection pool 9 | spring.datasource.hikari.connection-test-query=SELECT 1 FROM DUAL 10 | spring.datasource.hikari.connection-timeout=2000 11 | spring.datasource.hikari.maximum-pool-size=3 12 | spring.datasource.hikari.max-lifetime=180000 13 | spring.datasource.hikari.minimum-idle=1 14 | 15 | # consul config 16 | consul.host=agate-consul 17 | consul.port=8500 -------------------------------------------------------------------------------- /agate-admin/src/main/resources/application-develop.properties: -------------------------------------------------------------------------------- 1 | 2 | #jdbc datasource 3 | spring.datasource.url=jdbc:sqlite:agate-script/agate.db 4 | spring.datasource.driver-class-name=org.sqlite.JDBC 5 | spring.datasource.username=root 6 | spring.datasource.password=123456 7 | 8 | # datasource connection pool 9 | spring.datasource.hikari.connection-test-query=SELECT 1 FROM DUAL 10 | spring.datasource.hikari.connection-timeout=2000 11 | spring.datasource.hikari.maximum-pool-size=3 12 | spring.datasource.hikari.max-lifetime=180000 13 | spring.datasource.hikari.minimum-idle=1 14 | 15 | # consul config 16 | consul.host=192.168.1.120 17 | consul.port=8500 -------------------------------------------------------------------------------- /agate-admin/src/main/resources/application-release.properties: -------------------------------------------------------------------------------- 1 | 2 | #jdbc datasource 3 | spring.datasource.url=jdbc:mysql://${mysql_host}:3306/agate?useUnicode=true&characterEncoding=utf-8 4 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 5 | spring.datasource.username=${mysql_username} 6 | spring.datasource.password=${mysql_password} 7 | 8 | # datasource connection pool 9 | spring.datasource.hikari.connection-test-query=SELECT 1 FROM DUAL 10 | spring.datasource.hikari.connection-timeout=2000 11 | spring.datasource.hikari.maximum-pool-size=5 12 | spring.datasource.hikari.max-lifetime=180000 13 | spring.datasource.hikari.minimum-idle=3 14 | 15 | # consul config 16 | consul.host=${consul_host} 17 | consul.port=8500 -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js: -------------------------------------------------------------------------------- 1 | import{d as s,q as a,o as e,c as t,e as r,w as o,n as l,a as d,j as n,f as i,a1 as p,H as c}from"./index-5b8751dc.js";/* empty css */const m={class:"mb-20px pb-20px",style:{"border-bottom":"1px solid var(--el-border-color)"}},b=s({__name:"ContentDetailWrap",props:{title:a.string.def(""),message:a.string.def("")},setup(s){const{getPrefixCls:a}=n(),b=a("content-detail-wrap");return(s,a)=>(e(),t("div",{class:l([`${d(b)}-container`,"relative"])},[r(d(c),{class:l([`${d(b)}-body`,"mb-20px"]),shadow:"never"},{default:o((()=>[i("div",m,[p(s.$slots,"header")]),p(s.$slots,"default")])),_:3},8,["class"])],2))}});export{b as _}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/test/resources/config2.json: -------------------------------------------------------------------------------- 1 | { 2 | "cluster": { 3 | "code": "product", 4 | "env": "release" 5 | }, 6 | "vertx": { 7 | "workerPoolSize": 4, 8 | "eventLoopPoolSize": 4, 9 | "blockedThreadCheckInterval": 1000000000 10 | }, 11 | "verticle": { 12 | "manage.instances": 2, 13 | "system.instances": 2 14 | }, 15 | "manage": { 16 | "port": 6464 17 | }, 18 | "consul": { 19 | "host": "127.0.0.1", 20 | "port": 8500 21 | }, 22 | "redis": { 23 | "host": "127.0.0.1", 24 | "port": 6379, 25 | "maxTotal": 8, 26 | "minIdle": 1, 27 | "timeout": 2000, 28 | "maxWaitMillis": 3000, 29 | "numTestsPerEvictionRun": -1, 30 | "minEvictableIdleTimeMillis": 60000, 31 | "timeBetweenEvictionRunsMillis": 30000 32 | } 33 | } -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Write.vue_vue_type_script_setup_true_lang-5ad32267.js: -------------------------------------------------------------------------------- 1 | import{u as e,F as a}from"./useForm-95be4c91.js";import{u as s}from"./useValidator-0a43379b.js";import{d as r,s as t,z as o,o as m,i,a as u}from"./index-5b8751dc.js";const n=r({__name:"Write",props:{currentRow:{type:Object,default:()=>null},formSchema:{type:Array,default:()=>[]}},setup(r,{expose:n}){const c=r,{required:l}=s(),d=t({code:[l()],name:[l()]}),{formRegister:p,formMethods:f}=e(),{setValues:h,getFormData:g,getElFormExpose:w}=f;return o((()=>c.currentRow),(e=>{e&&h(e)}),{deep:!0,immediate:!0}),n({submit:async()=>{const e=await w();if(await(null==e?void 0:e.validate().catch((e=>{})))){return await g()}}}),(e,s)=>(m(),i(u(a),{rules:d,onRegister:u(p),schema:r.formSchema},null,8,["rules","onRegister","schema"]))}});export{n as _}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Write.vue_vue_type_script_setup_true_lang-c8502536.js: -------------------------------------------------------------------------------- 1 | import{u as e,F as a}from"./useForm-95be4c91.js";import{u as s}from"./useValidator-0a43379b.js";import{d as r,s as t,z as o,o as m,i,a as u}from"./index-5b8751dc.js";const n=r({__name:"Write",props:{currentRow:{type:Object,default:()=>null},formSchema:{type:Array,default:()=>[]}},setup(r,{expose:n}){const l=r,{required:c}=s(),d=t({gwId:[c()],name:[c()]}),{formRegister:p,formMethods:f}=e(),{setValues:g,getFormData:h,getElFormExpose:w}=f;return o((()=>l.currentRow),(e=>{e&&g(e)}),{deep:!0,immediate:!0}),n({submit:async()=>{const e=await w();if(await(null==e?void 0:e.validate().catch((e=>{})))){return await h()}}}),(e,s)=>(m(),i(u(a),{rules:d,onRegister:u(p),schema:r.formSchema},null,8,["rules","onRegister","schema"]))}});export{n as _}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail.vue_vue_type_script_setup_true_lang-61edcffb.js: -------------------------------------------------------------------------------- 1 | import{D as e}from"./Descriptions-e6f4f0ea.js";import{d as a,s,e as l,J as t,B as n,o as i,i as r,a as o,k as f}from"./index-5b8751dc.js";const d=a({__name:"Detail",props:{currentRow:{type:Object,default:()=>null}},setup(a){const{t:d}=f(),p=s([{field:"cname",label:d("集群")},{field:"name",label:d("网关")},{field:"port",label:d("端口")},{field:"status",label:d("状态"),slots:{default:e=>0===e.status?l(n("el-tag"),{type:"info"},{default:()=>[t("已停止")]}):l(n("el-tag"),{type:"success"},{default:()=>[t("已启动")]})}},{field:"remark",label:d("备注"),span:24},{field:"serverConfig",label:d("服务端配置"),span:24},{field:"clientConfig",label:d("客户端配置"),span:24}]);return(s,l)=>(i(),r(o(e),{schema:p,data:a.currentRow||{}},null,8,["schema","data"]))}});export{d as _}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/CarType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | public enum CarType { 19 | small, big 20 | 21 | } 22 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/options/ParamType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.options; 17 | 18 | public enum ParamType { 19 | HEADER, QUERY, PATH; 20 | } 21 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/ParamType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | public enum ParamType { 19 | HEADER, QUERY, PATH; 20 | } 21 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/service/Loadbalancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.service; 17 | 18 | public interface Loadbalancer { 19 | 20 | String choose(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/service/ServiceAddress.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.service; 17 | 18 | public interface ServiceAddress { 19 | 20 | String getUrl(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail-da843398.js: -------------------------------------------------------------------------------- 1 | import a from"./Show-61508f13.js";import{_ as t}from"./ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js";import{d as e,Z as s,u as o,r,o as i,i as l,w as m,e as u,J as n,t as p,a as d,O as _,k as c}from"./index-5b8751dc.js";/* empty css */import{b as f}from"./route-9803be03.js";/* empty css */import"./index-e446de42.js";const j=e({__name:"Detail",setup(e){const{t:j}=c(),{query:k}=s(),{push:v,go:w}=o(),x=r();return(async()=>{const a=await f(k.id);a&&(x.value=a.data)})(),(e,s)=>(i(),l(d(t),{title:d(j)("exampleDemo.detail"),onBack:s[1]||(s[1]=a=>d(v)("/gateway/list"))},{header:m((()=>[u(d(_),{onClick:s[0]||(s[0]=a=>d(w)(-1))},{default:m((()=>[n(p(d(j)("common.back")),1)])),_:1})])),default:m((()=>[u(a,{model:x.value},null,8,["model"])])),_:1},8,["title"]))}});export{j as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/el-card-48e750da.css: -------------------------------------------------------------------------------- 1 | .el-card{--el-card-border-color:var(--el-border-color-light);--el-card-border-radius:4px;--el-card-padding:20px;--el-card-bg-color:var(--el-fill-color-blank);background-color:var(--el-card-bg-color);border:1px solid var(--el-card-border-color);border-radius:var(--el-card-border-radius);color:var(--el-text-color-primary);overflow:hidden;transition:var(--el-transition-duration)}.el-card.is-always-shadow{box-shadow:var(--el-box-shadow-light)}.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{box-shadow:var(--el-box-shadow-light)}.el-card__header{border-bottom:1px solid var(--el-card-border-color);box-sizing:border-box;padding:calc(var(--el-card-padding) - 2px) var(--el-card-padding)}.el-card__body{padding:var(--el-card-padding)}.el-card__footer{border-top:1px solid var(--el-card-border-color);box-sizing:border-box;padding:calc(var(--el-card-padding) - 2px) var(--el-card-padding)} 2 | -------------------------------------------------------------------------------- /agate-gateway/src/test/resources/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "gateway": { 3 | "cluster": "product" 4 | }, 5 | "tracing": { 6 | "serviceName": "agate-gateway", 7 | "probability": 1.0, 8 | "senderOptions": { 9 | "endpoint": "http://localhost:9411/api/v2/spans" 10 | } 11 | }, 12 | "vertx": { 13 | "workerPoolSize": 4, 14 | "eventLoopPoolSize": 4, 15 | "blockedThreadCheckInterval": 1000000000 16 | }, 17 | "verticle": { 18 | "manage.instances": 2, 19 | "system.instances": 2 20 | }, 21 | "manage": { 22 | "port": 5454 23 | }, 24 | "consul": { 25 | "host": "192.168.1.120", 26 | "port": 8500 27 | }, 28 | "redis": { 29 | "host": "127.0.0.1", 30 | "port": 6379, 31 | "maxTotal": 8, 32 | "minIdle": 1, 33 | "timeout": 2000, 34 | "maxWaitMillis": 3000, 35 | "numTestsPerEvictionRun": -1, 36 | "minEvictableIdleTimeMillis": 60000, 37 | "timeBetweenEvictionRunsMillis": 30000 38 | } 39 | } -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/port/AccountRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.port; 17 | 18 | import io.agate.admin.business.model.UserDefinition; 19 | 20 | public interface AccountRepository { 21 | 22 | UserDefinition find(String username); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/context/ContextConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.context; 17 | 18 | public class ContextConstants { 19 | 20 | public static final String BACKEND_RESPONSE = "backend.response"; 21 | 22 | public static final String BACKEND_REQUEST = "backend.request"; 23 | } 24 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Detail-0bfbc759.js: -------------------------------------------------------------------------------- 1 | import{_ as t}from"./Detail.vue_vue_type_script_setup_true_lang-61edcffb.js";import{_ as a}from"./ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js";import{d as e,Z as s,u as r,r as o,o as i,i as p,w as l,e as u,J as n,t as m,a as _,O as c,k as d}from"./index-5b8751dc.js";import{e as j}from"./gateway-29ace984.js";/* empty css */import"./Descriptions-e6f4f0ea.js";/* empty css *//* empty css */import"./index-e446de42.js";const f=e({__name:"Detail",setup(e){const{t:f}=d(),{query:v}=s(),{push:w,go:y}=r(),g=o(null);return(async()=>{const t=await j(v.id);t&&(g.value=t.data)})(),(e,s)=>(i(),p(_(a),{title:_(f)("exampleDemo.detail"),onBack:s[1]||(s[1]=t=>_(w)("/gateway/list"))},{header:l((()=>[u(_(c),{onClick:s[0]||(s[0]=t=>_(y)(-1))},{default:l((()=>[n(m(_(f)("common.back")),1)])),_:1})])),default:l((()=>[u(t,{"current-row":g.value},null,8,["current-row"])])),_:1},8,["title"]))}});export{f as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/param/GatewayQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.param; 17 | 18 | public class GatewayQuery extends PageQuery { 19 | 20 | private String ccode; 21 | 22 | public String getCcode() { 23 | return ccode; 24 | } 25 | 26 | public void setCcode(String ccode) { 27 | this.ccode = ccode; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/param/RouteQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.param; 17 | 18 | public class RouteQuery extends PageQuery { 19 | 20 | private Integer appId; 21 | 22 | public Integer getAppId() { 23 | return appId; 24 | } 25 | 26 | public void setAppId(Integer appId) { 27 | this.appId = appId; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /agate-script/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | consul: 5 | image: consul:1.7 6 | container_name: agate-consul 7 | # restart: always 8 | ports: 9 | - 8500:8500 10 | volumes: 11 | - ./consul:/consul/data 12 | 13 | admin: 14 | image: agate/admin:1.2.0 15 | # build: ./ 16 | container_name: agate-admin 17 | # restart: always 18 | ports: 19 | - 8888:8888 20 | environment: 21 | ACTIVE_PROFILE: "install" 22 | volumes: 23 | - ./admin/logs:/agate-admin/logs 24 | - ./admin/data:/agate-admin/data 25 | - ./admin/config:/agate-admin/config 26 | depends_on: 27 | - consul 28 | 29 | gateway: 30 | image: agate/gateway:1.2.0 31 | # build: ./ 32 | container_name: agate-gateway 33 | # restart: always 34 | ports: 35 | - 4444:4444 36 | - 4004:4004 37 | volumes: 38 | - ./gateway/logs:/agate-gateway/logs 39 | - ./gateway/config:/agate-gateway/config 40 | depends_on: 41 | - consul 42 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/service/ServiceAddressSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.service; 17 | 18 | import java.util.List; 19 | import java.util.function.Supplier; 20 | 21 | public interface ServiceAddressSupplier extends Supplier> { 22 | 23 | public String getServiceId(); 24 | 25 | public void close(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Error.vue_vue_type_script_setup_true_lang-bc8e476e.js: -------------------------------------------------------------------------------- 1 | import{d as e,q as r,o as s,c as t,f as o,t as a,e as n,w as i,a as l,k as c,J as u,O as m}from"./index-5b8751dc.js";/* empty css */const p={class:"flex justify-center"},d={class:"text-center"},f=["src"],x={class:"text-14px text-[var(--el-color-info)]"},g={class:"mt-20px"},v=e({__name:"Error",props:{type:r.string.validate((e=>["404","500","403"].includes(e))).def("404")},emits:["errorClick"],setup(e,{emit:r}){const v=e,{t:y}=c(),T={404:{url:"/assets/404-1759fece.svg",message:y("error.pageError"),buttonText:y("error.returnToHome")},500:{url:"/assets/500-8fda557c.svg",message:y("error.networkError"),buttonText:y("error.returnToHome")},403:{url:"/assets/403-af24f6bf.svg",message:y("error.noPermission"),buttonText:y("error.returnToHome")}},b=()=>{r("errorClick",v.type)};return(r,c)=>(s(),t("div",p,[o("div",d,[o("img",{width:"350",src:T[e.type].url,alt:""},null,8,f),o("div",x,a(T[e.type].message),1),o("div",g,[n(l(m),{type:"primary",onClick:b},{default:i((()=>[u(a(T[e.type].buttonText),1)])),_:1})])])]))}});export{v as _}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/AgateGatewayLauncherTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | import io.agate.gateway.context.AgateVerticleFactory; 19 | import io.agate.gateway.verticle.LaunchVerticle; 20 | 21 | class AgateGatewayLauncherTest { 22 | 23 | public static void main(String[] args) throws Exception { 24 | AgateGatewayLauncher.main(new String[] { "run", AgateVerticleFactory.verticleName(LaunchVerticle.class) }); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/AgateGatewayLauncherTest3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | class AgateGatewayLauncherTest3 { 19 | 20 | public static void main(String[] args) throws Exception { 21 | if (args != null) { 22 | for (int i = 0; i < args.length; i++) { 23 | System.out.println("arg[" + i + "] = " + args[i]); 24 | } 25 | } 26 | AgateGatewayLauncher.main(args); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/OrderedTest.java: -------------------------------------------------------------------------------- 1 | package io.agate.gateway; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import io.agate.gateway.handler.OrderedHandler; 7 | import io.vertx.ext.web.RoutingContext; 8 | 9 | public class OrderedTest { 10 | 11 | public static void main(String[] args) { 12 | List hs = new ArrayList<>(); 13 | hs.add(new OrderedHandler(600) { 14 | @Override 15 | public void handle(RoutingContext event) { 16 | 17 | } 18 | }); 19 | hs.add(new OrderedHandler(500) { 20 | @Override 21 | public void handle(RoutingContext event) { 22 | 23 | } 24 | }); 25 | hs.add(new OrderedHandler(Integer.MIN_VALUE) { 26 | @Override 27 | public void handle(RoutingContext event) { 28 | 29 | } 30 | }); 31 | 32 | hs.forEach(h -> { 33 | System.out.println(h.getOrder()); 34 | }); 35 | hs.sort(null); 36 | hs.forEach(h -> { 37 | System.out.println(h.getOrder()); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/port/CatalogRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.port; 17 | 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.Optional; 21 | 22 | public interface CatalogRepository { 23 | 24 | void deleteKey(String key); 25 | 26 | List getKeys(String key); 27 | 28 | Optional getValue(String k); 29 | 30 | void putValue(String key, String value); 31 | 32 | List> getMetas(String service); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/BusinessException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business; 17 | 18 | public class BusinessException extends Exception { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | private int code; 23 | 24 | public BusinessException(int code, String message) { 25 | super(message); 26 | this.code = code; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | 33 | public void setCode(int code) { 34 | this.code = code; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/context/AddressConstant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.context; 17 | 18 | public interface AddressConstant { 19 | 20 | String GATEWAY_START = "gateway:start"; 21 | String GATEWAY_CLOSE = "gateway:close"; 22 | 23 | String ROUTE_DEPLOY = "route:deploy"; 24 | String ROUTE_REMOVE = "route:remove"; 25 | String ROUTE_UPDATE = "route:update"; 26 | 27 | String APM_METRICS = "apm.metrics"; 28 | 29 | String CIRCUIT_BREAKER = "vertx.circuit-breaker"; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/AgateGatewayLauncherTest2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | import io.agate.gateway.context.AgateVerticleFactory; 19 | import io.agate.gateway.verticle.LaunchVerticle; 20 | 21 | class AgateGatewayLauncherTest2 { 22 | 23 | public static void main(String[] args) throws Exception { 24 | AgateGatewayLauncher.main(new String[] { "run", AgateVerticleFactory.verticleName(LaunchVerticle.class), 25 | "-conf=src/test/resources/config2.json" }); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/service/DefaultServiceAddress.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.service; 17 | 18 | public class DefaultServiceAddress implements ServiceAddress { 19 | 20 | private String url; 21 | 22 | public DefaultServiceAddress(String url) { 23 | this.url = url; 24 | } 25 | 26 | @Override 27 | public String getUrl() { 28 | return url; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "DefaultServiceAddress [url=" + url + "]"; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/handler/RouteHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.handler; 17 | 18 | import io.vertx.core.Handler; 19 | import io.vertx.ext.web.RoutingContext; 20 | 21 | /** 22 | * The RouteHandler is responsible for processing requests. 23 | * A route holds multiple RouteHandler, which are shared by multiple route processing threads. 24 | * When a route is removed, the RouteHandler needs to destroy and release resources. 25 | */ 26 | public interface RouteHandler extends Handler { 27 | 28 | default void destroy() { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/port/AppRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.port; 17 | 18 | import java.util.List; 19 | 20 | import io.agate.admin.business.model.AppDefinition; 21 | 22 | public interface AppRepository { 23 | 24 | boolean appNameExist(String name); 25 | 26 | void create(AppDefinition entity); 27 | 28 | void update(AppDefinition entity); 29 | 30 | List list(); 31 | 32 | AppDefinition find(Integer id); 33 | 34 | void delete(Integer id); 35 | 36 | int total(); 37 | 38 | List find(int start, int size); 39 | 40 | } -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/port/ClusterRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.port; 17 | 18 | import java.util.List; 19 | 20 | import io.agate.admin.business.model.ClusterDefinition; 21 | 22 | public interface ClusterRepository { 23 | 24 | boolean clusterNameExist(String code); 25 | 26 | void create(ClusterDefinition defination); 27 | 28 | void update(ClusterDefinition definition); 29 | 30 | List list(); 31 | 32 | ClusterDefinition find(Integer id); 33 | 34 | ClusterDefinition find(String code); 35 | 36 | void delete(Integer id); 37 | 38 | } -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/param/PageQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.param; 17 | 18 | public class PageQuery { 19 | 20 | protected Integer pageSize; 21 | protected Integer pageIndex; 22 | 23 | public PageQuery() { 24 | super(); 25 | } 26 | 27 | public Integer getPageSize() { 28 | return pageSize; 29 | } 30 | 31 | public void setPageSize(Integer pageSize) { 32 | this.pageSize = pageSize; 33 | } 34 | 35 | public Integer getPageIndex() { 36 | return pageIndex; 37 | } 38 | 39 | public void setPageIndex(Integer pageIndex) { 40 | this.pageIndex = pageIndex; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Add-978396b6.js: -------------------------------------------------------------------------------- 1 | import a from"./Write-b0fd3506.js";import{_ as e}from"./ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js";import{d as t,u as s,Z as o,r,o as i,i as l,w as m,e as n,J as p,t as u,a as d,O as c,k as f}from"./index-5b8751dc.js";/* empty css */import{a as _}from"./route-9803be03.js";import{u as y}from"./useEmitt-76f9af94.js";/* empty css */import"./index-e446de42.js";const j=t({__name:"Add",setup(t){const{t:j}=f(),{emitter:v}=y(),{push:k,go:g}=s(),{query:x}=o(),C=r(),h=r(!1),w=async()=>{const a=d(C),e=await(null==a?void 0:a.submitForm());if(e){h.value=!0,e.appId=x.app;await _(e).catch((()=>{})).finally((()=>{h.value=!1}))&&(v.emit("changeEvent","add"),g(-1))}},b=async()=>{const a=d(C);null==a||a.resetForm()};return(t,s)=>(i(),l(d(e),{title:d(j)("exampleDemo.add"),onBack:s[1]||(s[1]=a=>d(k)("/app/route/list"))},{header:m((()=>[n(d(c),{onClick:s[0]||(s[0]=a=>d(g)(-1))},{default:m((()=>[p(u(d(j)("common.back")),1)])),_:1}),n(d(c),{type:"primary",onClick:b},{default:m((()=>[p(u(d(j)("common.reset")),1)])),_:1}),n(d(c),{type:"primary",loading:h.value,onClick:w},{default:m((()=>[p(u(d(j)("exampleDemo.save")),1)])),_:1},8,["loading"])])),default:m((()=>[n(a,{ref_key:"writeRef",ref:C},null,512)])),_:1},8,["title"]))}});export{j as default}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/RouteHandlerPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.options.RouteOptions; 20 | import io.vertx.core.Vertx; 21 | 22 | /** 23 | * The RouteHandlerPlugin is responsible for creating a RouteHandler. 24 | */ 25 | public abstract class RouteHandlerPlugin { 26 | 27 | public abstract RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions); 28 | 29 | public boolean failure() { 30 | return false; 31 | } 32 | 33 | public void destroy() { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Add-27afb4b3.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./Write.vue_vue_type_script_setup_true_lang-c9eb325e.js";import{_ as t}from"./ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js";import{d as a,u as s,r as i,o as r,i as o,w as l,e as m,J as p,t as u,a as n,O as d,k as _}from"./index-5b8751dc.js";/* empty css */import{b as c}from"./gateway-29ace984.js";import{u as f}from"./useEmitt-76f9af94.js";import"./useForm-95be4c91.js";/* empty css */import"./tsxHelper-11a4c46e.js";/* empty css */import"./useValidator-0a43379b.js";/* empty css */import"./index-e446de42.js";const j=a({__name:"Add",setup(a){const{t:j}=_(),{emitter:v}=f(),{push:y,go:g}=s(),w=i(),k=i(!1),x=async()=>{const e=n(w),t=await(null==e?void 0:e.submit());if(t){k.value=!0;await c(t).catch((()=>{})).finally((()=>{k.value=!1}))&&(v.emit("changeEvent","add"),y("/gateway/list"))}};return(a,s)=>(r(),o(n(t),{title:n(j)("exampleDemo.add"),onBack:s[1]||(s[1]=e=>n(y)("/gateway/list"))},{header:l((()=>[m(n(d),{onClick:s[0]||(s[0]=e=>n(g)(-1))},{default:l((()=>[p(u(n(j)("common.back")),1)])),_:1}),m(n(d),{type:"primary",loading:k.value,onClick:x},{default:l((()=>[p(u(n(j)("exampleDemo.save")),1)])),_:1},8,["loading"])])),default:l((()=>[m(e,{ref_key:"writeRef",ref:w},null,512)])),_:1},8,["title"]))}});export{j as default}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/AccessLogPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.AccessLogHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.vertx.core.Vertx; 24 | 25 | public class AccessLogPlugin extends RouteHandlerPlugin { 26 | 27 | @Override 28 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 29 | return new AccessLogHandler(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/ProxyReplyPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.ProxyReplyHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.vertx.core.Vertx; 24 | 25 | public class ProxyReplyPlugin extends RouteHandlerPlugin { 26 | 27 | @Override 28 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 29 | return new ProxyReplyHandler(routeOptions); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/MeterMetricsPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.MeterMetricsHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.vertx.core.Vertx; 24 | 25 | public class MeterMetricsPlugin extends RouteHandlerPlugin { 26 | 27 | @Override 28 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 29 | return new MeterMetricsHandler(routeOptions); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/RateLimitPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.RateLimitHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.vertx.core.Vertx; 24 | 25 | public class RateLimitPlugin extends RouteHandlerPlugin { 26 | 27 | @Override 28 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 29 | return new RateLimitHandler(vertx, routeOptions, pluginOptions); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/ZipkinTracingPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.ZipkinTracingHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.vertx.core.Vertx; 24 | 25 | public class ZipkinTracingPlugin extends RouteHandlerPlugin { 26 | 27 | @Override 28 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 29 | return new ZipkinTracingHandler(routeOptions); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Edit-321cbe46.js: -------------------------------------------------------------------------------- 1 | import e from"./Write-b0fd3506.js";import{_ as t}from"./ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js";import{d as a,Z as s,u as o,r as i,o as r,i as l,w as m,e as n,J as u,t as c,a as p,O as d,k as f}from"./index-5b8751dc.js";/* empty css */import{u as _}from"./useEmitt-76f9af94.js";import{b as y,a as v}from"./route-9803be03.js";/* empty css */import"./index-e446de42.js";const j=a({__name:"Edit",setup(a){const{t:j}=f(),{query:k}=s(),{emitter:g}=_(),{push:w,go:x}=o(),C=i();(async()=>{const e=await y(k.id);e&&(C.value=e.data)})();const b=i(),h=i(!1),D=async()=>{const e=p(b),t=await(null==e?void 0:e.submitForm());if(t){h.value=!0;await v(t).catch((()=>{})).finally((()=>{h.value=!1}))&&(g.emit("changeEvent","editor"),x(-1))}},E=async()=>{const e=p(b);null==e||e.resetForm()};return(a,s)=>(r(),l(p(t),{title:p(j)("exampleDemo.edit"),onBack:s[1]||(s[1]=e=>p(w)("/gateway/list"))},{header:m((()=>[n(p(d),{onClick:s[0]||(s[0]=e=>p(x)(-1))},{default:m((()=>[u(c(p(j)("common.back")),1)])),_:1}),n(p(d),{type:"primary",onClick:E},{default:m((()=>[u(c(p(j)("common.reset")),1)])),_:1}),n(p(d),{type:"primary",loading:h.value,onClick:D},{default:m((()=>[u(c(p(j)("exampleDemo.save")),1)])),_:1},8,["loading"])])),default:m((()=>[n(e,{ref_key:"writeRef",ref:b,model:C.value},null,8,["model"])])),_:1},8,["title"]))}});export{j as default}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/CircuitBreakerPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.CircuitBreakerHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.vertx.core.Vertx; 24 | 25 | public class CircuitBreakerPlugin extends RouteHandlerPlugin { 26 | 27 | @Override 28 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 29 | return new CircuitBreakerHandler(vertx, routeOptions, pluginOptions); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/useCrudSchemas-2c80f3ed.js: -------------------------------------------------------------------------------- 1 | import{t as e,f as l,e as n}from"./tree-91585a69.js";import{s as o}from"./index-5b8751dc.js";const d=e=>{const l=o({searchSchema:[],tableColumns:[],formSchema:[],detailSchema:[]}),n=t(e);l.searchSchema=n||[];const d=i(e);l.tableColumns=d||[];const s=a(e);l.formSchema=s;const c=r(e);return l.detailSchema=c,{allSchemas:l}},t=e=>{var l,n,o;const d=[],t=e.length;for(let i=0;i{const o=e(n,{conversion:e=>{var l;if(!(null==(l=null==e?void 0:e.table)?void 0:l.hidden))return{...e,...e.table}}});return l(o,(e=>(void 0===e.children&&delete e.children,!!e.field)))},a=e=>{var l,n,o;const d=[],t=e.length;for(let i=0;i{const l=[];return n(e,(e=>{var n,o;if(!(null==(n=null==e?void 0:e.detail)?void 0:n.hidden)){const n={...e.detail,field:e.field,label:(null==(o=e.detail)?void 0:o.label)||e.label};delete n.hidden,l.push(n)}})),l};export{d as u}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/RestfulFailurePlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.RestfulFailureHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.vertx.core.Vertx; 24 | 25 | public class RestfulFailurePlugin extends RouteHandlerPlugin { 26 | 27 | @Override 28 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 29 | return new RestfulFailureHandler(Integer.MAX_VALUE); 30 | } 31 | 32 | @Override 33 | public boolean failure() { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Edit-94a229f6.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./Write.vue_vue_type_script_setup_true_lang-c9eb325e.js";import{_ as t}from"./ContentDetailWrap.vue_vue_type_script_setup_true_lang-faadb3d0.js";import{d as a,Z as s,u as r,r as i,o,i as l,w as u,e as m,J as p,t as n,a as c,O as d,k as _}from"./index-5b8751dc.js";/* empty css */import{e as f,b as j}from"./gateway-29ace984.js";import{u as v}from"./useEmitt-76f9af94.js";import"./useForm-95be4c91.js";/* empty css */import"./tsxHelper-11a4c46e.js";/* empty css */import"./useValidator-0a43379b.js";/* empty css */import"./index-e446de42.js";const y=a({__name:"Edit",setup(a){const{t:y}=_(),{query:w}=s(),{emitter:g}=v(),{push:k,go:x}=r(),b=i(null);(async()=>{const e=await f(w.id);e&&(b.value=e.data)})();const h=i(),C=i(!1),D=async()=>{const e=c(h),t=await(null==e?void 0:e.submit());if(t){C.value=!0;await j(t).catch((()=>{})).finally((()=>{C.value=!1}))&&(g.emit("changeEvent","editor"),k("/gateway/list"))}};return(a,s)=>(o(),l(c(t),{title:c(y)("exampleDemo.edit"),onBack:s[1]||(s[1]=e=>c(k)("/gateway/list"))},{header:u((()=>[m(c(d),{onClick:s[0]||(s[0]=e=>c(x)(-1))},{default:u((()=>[p(n(c(y)("common.back")),1)])),_:1}),m(c(d),{type:"primary",loading:C.value,onClick:D},{default:u((()=>[p(n(c(y)("exampleDemo.save")),1)])),_:1},8,["loading"])])),default:u((()=>[m(e,{ref_key:"writeRef",ref:h,"current-row":b.value},null,8,["current-row"])])),_:1},8,["title"]))}});export{y as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/port/GatewayRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.port; 17 | 18 | import java.util.List; 19 | 20 | import io.agate.admin.business.model.GatewayDefinition; 21 | 22 | public interface GatewayRepository { 23 | 24 | boolean gatewayNameExist(GatewayDefinition definition); 25 | 26 | boolean hasGatewaysByClusterCode(String cluster); 27 | 28 | void create(GatewayDefinition entity); 29 | 30 | void update(GatewayDefinition entity); 31 | 32 | List list(); 33 | 34 | GatewayDefinition find(Integer id); 35 | 36 | GatewayDefinition find(String cluster, String gateway); 37 | 38 | void delete(Integer id); 39 | 40 | void updateStatus(GatewayDefinition entity); 41 | 42 | List find(String name, int start, int size); 43 | 44 | int total(String name); 45 | 46 | } -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/port/RouteRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.port; 17 | 18 | import java.util.List; 19 | 20 | import io.agate.admin.business.model.RouteDefinition; 21 | 22 | public interface RouteRepository { 23 | 24 | boolean routeNameExist(String name); 25 | 26 | void create(RouteDefinition definition); 27 | 28 | void update(RouteDefinition definition); 29 | 30 | List list(); 31 | 32 | List list(Integer appId); 33 | 34 | List listByGatewayId(Integer gwId); 35 | 36 | RouteDefinition find(Integer id); 37 | 38 | void delete(Integer id); 39 | 40 | void updateStatus(RouteDefinition definition); 41 | 42 | void deleteByGatewayId(Integer gwId); 43 | 44 | int total(Integer appId); 45 | 46 | List find(Integer appId, int start, int size); 47 | 48 | } -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/internal/HttpProxyPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin.internal; 17 | 18 | import io.agate.gateway.handler.RouteHandler; 19 | import io.agate.gateway.handler.internal.HttpProxyHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.agate.gateway.plugin.PluginOptions; 22 | import io.agate.gateway.plugin.RouteHandlerPlugin; 23 | import io.agate.gateway.service.Loadbalancer; 24 | import io.agate.gateway.service.ServiceAddressSupplier; 25 | import io.vertx.core.Vertx; 26 | import io.vertx.core.http.HttpClient; 27 | 28 | public class HttpProxyPlugin extends RouteHandlerPlugin { 29 | 30 | @Override 31 | public RouteHandler createHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 32 | return new HttpProxyHandler(vertx, routeOptions, pluginOptions); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Write.vue_vue_type_script_setup_true_lang-c9eb325e.js: -------------------------------------------------------------------------------- 1 | import{u as e,F as o}from"./useForm-95be4c91.js";import{d as t,s as r,z as s,o as a,i as n,a as p,k as l}from"./index-5b8751dc.js";import{u as m}from"./useValidator-0a43379b.js";import{g as i}from"./gateway-29ace984.js";const c=t({__name:"Write",props:{currentRow:{type:Object,default:()=>null}},setup(t,{expose:c}){const u=t,{t:d}=l(),{required:f}=m(),{formRegister:P,formMethods:b}=e(),{setValues:g,getFormData:w,getElFormExpose:I}=b,x=r([{field:"ccode",label:d("集群"),component:"Select",componentProps:{props:{label:"name",value:"code"}},optionApi:async()=>(await i()).data,formItemProps:{rules:[f()]},colProps:{span:24}},{field:"name",label:d("网关"),component:"Input",formItemProps:{rules:[f()]}},{field:"port",label:d("端口"),component:"InputNumber",componentProps:{controlsPosition:"right"},formItemProps:{rules:[f()]}},{field:"remark",label:d("备注"),component:"Input",componentProps:{type:"textarea",rows:2},colProps:{span:24}},{field:"serverConfig",label:d("服务端配置"),component:"Input",componentProps:{type:"textarea",rows:2},colProps:{span:24}},{field:"clientConfig",label:d("客户端配置"),component:"Input",componentProps:{type:"textarea",rows:2},colProps:{span:24}}]),y=r({ccode:[f()],name:[f()],port:[f()]});return s((()=>u.currentRow),(e=>{e&&g(e)}),{deep:!0,immediate:!0}),c({submit:async()=>{const e=await I();if(await(null==e?void 0:e.validate().catch((e=>{})))){return await w()}}}),(e,t)=>(a(),n(p(o),{rules:y,onRegister:p(P),schema:x},null,8,["rules","onRegister","schema"]))}});export{c as _}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/store/EmptyCatalogRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.store; 17 | 18 | import java.util.Collections; 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.Optional; 22 | 23 | import io.agate.admin.business.port.CatalogRepository; 24 | 25 | public class EmptyCatalogRepository implements CatalogRepository { 26 | 27 | @Override 28 | public void deleteKey(String key) { 29 | 30 | } 31 | 32 | @Override 33 | public List getKeys(String key) { 34 | return Collections.emptyList(); 35 | } 36 | 37 | @Override 38 | public Optional getValue(String k) { 39 | return Optional.empty(); 40 | } 41 | 42 | @Override 43 | public void putValue(String key, String value) { 44 | } 45 | 46 | @Override 47 | public List> getMetas(String service) { 48 | return Collections.emptyList(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/handler/internal/ZipkinTracingHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.handler.internal; 17 | 18 | import brave.Span; 19 | import io.agate.gateway.handler.OrderedHandler; 20 | import io.agate.gateway.options.RouteOptions; 21 | import io.vertx.ext.web.RoutingContext; 22 | import io.vertx.tracing.zipkin.ZipkinTracer; 23 | 24 | public class ZipkinTracingHandler extends OrderedHandler { 25 | 26 | private final RouteOptions routeOptions; 27 | 28 | public ZipkinTracingHandler(RouteOptions routeOptions) { 29 | super(200); 30 | this.routeOptions = routeOptions; 31 | } 32 | 33 | @Override 34 | public void handle(RoutingContext context) { 35 | Span activeSpan = ZipkinTracer.activeSpan(); 36 | if (activeSpan != null) { 37 | activeSpan.tag("route.name", routeOptions.getRoute()).tag("gateway.name", routeOptions.getGateway()); 38 | } 39 | context.next(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Workplace-1be4c26c.css: -------------------------------------------------------------------------------- 1 | .el-skeleton{--el-skeleton-color:var(--el-fill-color);--el-skeleton-to-color:var(--el-fill-color-darker)}@keyframes el-skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.el-skeleton{width:100%}.el-skeleton__first-line,.el-skeleton__paragraph{background:var(--el-skeleton-color);height:16px;margin-top:16px}.el-skeleton.is-animated .el-skeleton__item{animation:el-skeleton-loading 1.4s ease infinite;background:linear-gradient(90deg,var(--el-skeleton-color) 25%,var(--el-skeleton-to-color) 37%,var(--el-skeleton-color) 63%);background-size:400% 100%}.el-skeleton{--el-skeleton-circle-size:var(--el-avatar-size)}.el-skeleton__item{background:var(--el-skeleton-color);border-radius:var(--el-border-radius-base);display:inline-block;height:16px;width:100%}.el-skeleton__circle{border-radius:50%;height:var(--el-skeleton-circle-size);line-height:var(--el-skeleton-circle-size);width:var(--el-skeleton-circle-size)}.el-skeleton__button{border-radius:4px;height:40px;width:64px}.el-skeleton__p{width:100%}.el-skeleton__p.is-last{width:61%}.el-skeleton__p.is-first{width:33%}.el-skeleton__text{height:var(--el-font-size-small);width:100%}.el-skeleton__caption{height:var(--el-font-size-extra-small)}.el-skeleton__h1{height:var(--el-font-size-extra-large)}.el-skeleton__h3{height:var(--el-font-size-large)}.el-skeleton__h5{height:var(--el-font-size-medium)}.el-skeleton__image{align-items:center;border-radius:0;display:flex;justify-content:center;width:unset}.el-skeleton__image svg{color:var(--el-svg-monochrome-grey);fill:currentColor;height:22%;width:22%} 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/param/PageList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.param; 17 | 18 | import java.util.List; 19 | 20 | public class PageList { 21 | 22 | private int total; 23 | 24 | private List list; 25 | 26 | public PageList() { 27 | } 28 | 29 | public PageList(List list) { 30 | if (list != null) { 31 | this.total = list.size(); 32 | } 33 | this.list = list; 34 | } 35 | 36 | public PageList(int total) { 37 | this.total = total; 38 | } 39 | 40 | public PageList(List list, int total) { 41 | this.list = list; 42 | this.total = total; 43 | } 44 | 45 | public int getTotal() { 46 | return total; 47 | } 48 | 49 | public void setTotal(int total) { 50 | this.total = total; 51 | } 52 | 53 | public List getList() { 54 | return list; 55 | } 56 | 57 | public PageList setList(List list) { 58 | this.list = list; 59 | return this; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/param/AppDetail.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.param; 17 | 18 | import io.agate.admin.business.model.AppDefinition; 19 | import io.agate.admin.business.model.GatewayDefinition; 20 | 21 | public class AppDetail { 22 | 23 | private AppDefinition app; 24 | 25 | private GatewayDefinition gateway; 26 | 27 | public AppDetail() { 28 | } 29 | 30 | public AppDetail(AppDefinition app, GatewayDefinition gateway) { 31 | this.app = app; 32 | this.gateway = gateway; 33 | } 34 | 35 | public AppDefinition getApp() { 36 | return app; 37 | } 38 | 39 | public void setApp(AppDefinition app) { 40 | this.app = app; 41 | } 42 | 43 | public GatewayDefinition getGateway() { 44 | return gateway; 45 | } 46 | 47 | public void setGateway(GatewayDefinition gateway) { 48 | this.gateway = gateway; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/TimeSlot.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | import java.time.Duration; 19 | import java.time.LocalDateTime; 20 | 21 | public class TimeSlot { 22 | 23 | LocalDateTime startTime; 24 | LocalDateTime finishTime; 25 | SlotType slotType; 26 | 27 | long charge; 28 | 29 | long length; 30 | 31 | public TimeSlot(LocalDateTime st, LocalDateTime ft, SlotType type) { 32 | this.startTime = st; 33 | this.finishTime = ft; 34 | this.slotType = type; 35 | 36 | this.length = Duration.between(startTime, finishTime).toMinutes(); 37 | } 38 | 39 | public enum SlotType { 40 | day, night 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "TimeSlot [startTime=" + startTime + ", finishTime=" + finishTime + ", slotType=" + slotType 46 | + ", charge=" + charge + ", length=" + length + "]"; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/handler/internal/RestfulFailureHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.handler.internal; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import io.agate.gateway.handler.OrderedHandler; 22 | import io.agate.gateway.http.RestfulUtil; 23 | import io.vertx.ext.web.RoutingContext; 24 | 25 | public class RestfulFailureHandler extends OrderedHandler { 26 | 27 | public RestfulFailureHandler(int order) { 28 | super(order); 29 | } 30 | 31 | private static final Logger LOG = LoggerFactory.getLogger(RestfulFailureHandler.class); 32 | 33 | @Override 34 | public void handle(RoutingContext rc) { 35 | if (LOG.isDebugEnabled()) { 36 | LOG.debug("request [{}] error: {}", rc.request().path(), rc.failure()); 37 | } 38 | 39 | int statusCode = rc.statusCode(); 40 | if (statusCode == -1) { 41 | statusCode = 500; 42 | } 43 | if (!rc.response().ended()) { 44 | RestfulUtil.exception(rc, statusCode, rc.failure()); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/http/HttpUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.http; 17 | 18 | import java.util.List; 19 | 20 | import io.vertx.core.MultiMap; 21 | import io.vertx.core.http.HttpMethod; 22 | 23 | public class HttpUtil { 24 | 25 | public static boolean pathIsRegex(String routePath) { 26 | return routePath.indexOf("(") > 0 || routePath.indexOf("?<") > 0; 27 | } 28 | 29 | public static boolean hasBody(HttpMethod method) { 30 | return method == HttpMethod.POST || method == HttpMethod.PUT || method == HttpMethod.DELETE 31 | || method == HttpMethod.PATCH || method == HttpMethod.TRACE; 32 | } 33 | 34 | public static Boolean isChunked(MultiMap headers) { 35 | List te = headers.getAll("transfer-encoding"); 36 | if (te != null) { 37 | boolean chunked = false; 38 | for (String val : te) { 39 | if (val.equals("chunked")) { 40 | chunked = true; 41 | } else { 42 | return null; 43 | } 44 | } 45 | return chunked; 46 | } else { 47 | return false; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logs 5 | detail.log 6 | error.log 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/service/FixedServiceAddressSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.service; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import io.agate.gateway.options.RouteOptions; 22 | import io.vertx.core.Vertx; 23 | 24 | public class FixedServiceAddressSupplier implements ServiceAddressSupplier { 25 | 26 | private final List addresses = new ArrayList(); 27 | 28 | private final String serviceId; 29 | 30 | public FixedServiceAddressSupplier(Vertx vertx, RouteOptions routeOptions) { 31 | this.serviceId = routeOptions.getRoute(); 32 | 33 | for (Object url : routeOptions.getBackend().getUrls()) { 34 | addresses.add(new DefaultServiceAddress(url.toString())); 35 | } 36 | } 37 | 38 | @Override 39 | public List get() { 40 | return addresses; 41 | } 42 | 43 | @Override 44 | public String getServiceId() { 45 | return serviceId; 46 | } 47 | 48 | @Override 49 | public void close() { 50 | addresses.clear(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/repository/AccountRepositoryDao.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.repository; 17 | 18 | import java.util.List; 19 | 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.jdbc.core.BeanPropertyRowMapper; 22 | import org.springframework.jdbc.core.JdbcTemplate; 23 | import org.springframework.stereotype.Component; 24 | 25 | import io.agate.admin.business.model.UserDefinition; 26 | import io.agate.admin.business.port.AccountRepository; 27 | 28 | @Component 29 | public class AccountRepositoryDao implements AccountRepository { 30 | 31 | @Autowired 32 | private JdbcTemplate jdbcTemplate; 33 | 34 | @Override 35 | public UserDefinition find(String username) { 36 | 37 | String sql = "select username,password,enabled from t_user where enabled=1 and username = ?"; 38 | List ares = jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(UserDefinition.class), 39 | username); 40 | if (!ares.isEmpty()) { 41 | return ares.get(0); 42 | } 43 | return null; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/http/QueryCoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.http; 17 | 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | import io.netty.handler.codec.http.QueryStringDecoder; 22 | import io.netty.handler.codec.http.QueryStringEncoder; 23 | 24 | public class QueryCoder { 25 | 26 | private QueryStringDecoder decoder; 27 | 28 | private QueryStringEncoder encoder; 29 | 30 | public QueryCoder(String url) { 31 | decoder = new QueryStringDecoder(url); 32 | Map> params = decoder.parameters(); 33 | 34 | encoder = new QueryStringEncoder(decoder.uri()); 35 | params.forEach((k, vs) -> { 36 | vs.forEach((v -> encoder.addParam(k, v))); 37 | }); 38 | } 39 | 40 | public QueryCoder addParam(String k, String v) { 41 | encoder.addParam(k, v); 42 | return this; 43 | } 44 | 45 | public String uri() { 46 | return encoder.toString(); 47 | } 48 | 49 | public String raw() { 50 | return decoder.toString(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/deploy/ClusterDeploy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.deploy; 17 | 18 | import java.util.Map; 19 | import java.util.concurrent.ConcurrentHashMap; 20 | 21 | public class ClusterDeploy { 22 | 23 | private final Map deployMap = new ConcurrentHashMap<>(); 24 | 25 | private final String cluster; 26 | 27 | public ClusterDeploy(String cluster) { 28 | this.cluster = cluster; 29 | } 30 | 31 | public String getCluster() { 32 | return cluster; 33 | } 34 | 35 | public GatewayDeploy get(String name) { 36 | return deployMap.get(name); 37 | } 38 | 39 | public void put(GatewayDeploy deploy) { 40 | deployMap.put(deploy.getGatewayName(), deploy); 41 | } 42 | 43 | public GatewayDeploy remove(String name) { 44 | GatewayDeploy deploy = deployMap.remove(name); 45 | if (deploy != null) { 46 | deploy.destroy(); 47 | } 48 | return deploy; 49 | } 50 | 51 | public void destroy() { 52 | deployMap.clear(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/handler/OrderedHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.handler; 17 | 18 | public abstract class OrderedHandler implements RouteHandler, Comparable { 19 | 20 | private final int order; 21 | 22 | public OrderedHandler(int order) { 23 | this.order = order; 24 | } 25 | 26 | /** 27 | * Get the order value of this object. 28 | *

29 | * Higher values are interpreted as lower priority. As a consequence, the object 30 | * with the lowest value has the highest priority (somewhat analogous to Servlet 31 | * {@code load-on-startup} values). 32 | *

33 | * Same order values will result in arbitrary sort positions for the affected 34 | * objects. 35 | * 36 | * @return the order value 37 | */ 38 | public int getOrder() { 39 | return order; 40 | } 41 | 42 | @Override 43 | public int compareTo(OrderedHandler other) { 44 | if (other == null) { 45 | return -1; 46 | } 47 | 48 | return this.order >= other.order ? 1 : -1; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/PluginDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | public class PluginDefinition { 19 | 20 | /** 21 | * 0: routing; 1: failure; 22 | */ 23 | private int type; 24 | 25 | private int order; 26 | 27 | private String plugin; 28 | 29 | private String config; 30 | 31 | public int getOrder() { 32 | return order; 33 | } 34 | 35 | public void setOrder(int order) { 36 | this.order = order; 37 | } 38 | 39 | public String getPlugin() { 40 | return plugin; 41 | } 42 | 43 | public void setPlugin(String plugin) { 44 | this.plugin = plugin; 45 | } 46 | 47 | public int getType() { 48 | return type; 49 | } 50 | 51 | public void setType(int type) { 52 | this.type = type; 53 | } 54 | 55 | public String getConfig() { 56 | return config; 57 | } 58 | 59 | public void setConfig(String config) { 60 | this.config = config; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return "PluginDefination [type=" + type + ", order=" + order + ", plugin=" + plugin + ", config=" + config 66 | + "]"; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduce 2 | 3 | Agate is a cloud-native, fast, scalable, and async API Gateway. its core values are high performance and extensibility. 4 | 5 | # Dependency 6 | 7 | - Vert.x 4.3 8 | - Consul 1.7 9 | 10 | # Quick start 11 | 12 | ## Startup gateway and admin 13 | 14 | - step1: pull source and build 15 | 16 | ```shell 17 | git pull https://github.com/dinstone/agate.git 18 | 19 | // build 20 | cd agate 21 | mvn clean package 22 | ``` 23 | 24 | - step2: start agate admin and gateway 25 | 26 | Windows: 27 | ```shell 28 | cd agate-script 29 | .\agate-install.bat 30 | ``` 31 | 32 | Linux: 33 | ```shell 34 | cd agate-script 35 | ./agate-install.sh 36 | ``` 37 | 38 | or execute the following command: 39 | ```shell 40 | cd agate 41 | mvn clean install 42 | 43 | cd agate-script 44 | docker compose stop 45 | echo y | docker compose rm 46 | docker compose up -d 47 | ``` 48 | 49 | - step3: test agate admin and gateway services 50 | 51 | ```shell 52 | access agate admin using username/password = agate/123456 by url http://localhost:8888/ 53 | ``` 54 | 55 | ## Config Route and Url rewrite 56 | 57 | - Http URL Proxy: 58 | 59 | ```shell 60 | http://localhost:4004/(?.*) --> https://www.baidu.com/:url 61 | ``` 62 | 63 | - Http Microservice Discovery: 64 | 65 | ```shell 66 | http://localhost:4002/user-provider/(?.*) --> http://user-provider/:url 67 | ``` 68 | 69 | # Feature 70 | 71 | - Logging 72 | - Tracing 73 | - Metrics 74 | - Rate Limit 75 | - Circuit Breaker 76 | - Gray Deployment 77 | - Security Authenticate 78 | - Routing: Http Reverse Proxy 79 | - Routing: Http Service Discovery 80 | 81 | # Architecture 82 | 83 | ![System Architecture](https://github.com/dinstone/agate/wiki/imgs/arch00.png) 84 | 85 | # Other Documents 86 | 87 | goto wiki https://github.com/dinstone/agate/wiki 88 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/repository/entity/ClusterEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.repository.entity; 17 | 18 | import java.util.Date; 19 | 20 | public class ClusterEntity { 21 | 22 | private Integer id; 23 | 24 | private String code; 25 | 26 | private String name; 27 | 28 | private Date createTime; 29 | 30 | private Date updateTime; 31 | 32 | public Integer getId() { 33 | return id; 34 | } 35 | 36 | public void setId(Integer id) { 37 | this.id = id; 38 | } 39 | 40 | public String getCode() { 41 | return code; 42 | } 43 | 44 | public void setCode(String code) { 45 | this.code = code; 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public void setName(String name) { 53 | this.name = name; 54 | } 55 | 56 | public Date getCreateTime() { 57 | return createTime; 58 | } 59 | 60 | public void setCreateTime(Date createTime) { 61 | this.createTime = createTime; 62 | } 63 | 64 | public Date getUpdateTime() { 65 | return updateTime; 66 | } 67 | 68 | public void setUpdateTime(Date updateTime) { 69 | this.updateTime = updateTime; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/FrontendDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | public class FrontendDefinition { 19 | 20 | private String path; 21 | 22 | private String method; 23 | 24 | private String consumes; 25 | 26 | private String produces; 27 | 28 | public String getPath() { 29 | return path; 30 | } 31 | 32 | public void setPath(String path) { 33 | this.path = path; 34 | } 35 | 36 | public String getMethod() { 37 | return method; 38 | } 39 | 40 | public void setMethod(String method) { 41 | this.method = method; 42 | } 43 | 44 | public String getConsumes() { 45 | return consumes; 46 | } 47 | 48 | public void setConsumes(String consumes) { 49 | this.consumes = consumes; 50 | } 51 | 52 | public String getProduces() { 53 | return produces; 54 | } 55 | 56 | public void setProduces(String produces) { 57 | this.produces = produces; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "FrontendDefination [path=" + path + ", method=" + method + ", consumes=" + consumes + ", produces=" 63 | + produces + "]"; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/service/AuthenService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.service; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.stereotype.Component; 20 | 21 | import io.agate.admin.business.BusinessException; 22 | import io.agate.admin.business.model.UserDefinition; 23 | import io.agate.admin.business.port.AccountRepository; 24 | 25 | @Component 26 | public class AuthenService { 27 | 28 | @Autowired 29 | private AccountRepository accountRepository; 30 | 31 | public UserDefinition authen(String username, String password) throws BusinessException { 32 | if (username == null || username.isEmpty()) { 33 | throw new BusinessException(1001, "username is empty"); 34 | } 35 | if (password == null || password.isEmpty()) { 36 | throw new BusinessException(1002, "password is empty"); 37 | } 38 | 39 | UserDefinition user = accountRepository.find(username); 40 | if (user == null || !user.getPassword().equals(password)) { 41 | throw new BusinessException(1003, "username or password is error"); 42 | } 43 | user.setPassword(null); 44 | return user; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/ParamDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | public class ParamDefinition { 19 | 20 | private String feParamName; 21 | 22 | /** 23 | * Header/Query/Path 24 | */ 25 | private ParamType feParamType; 26 | 27 | private String beParamName; 28 | 29 | /** 30 | * Header/Query/Path 31 | */ 32 | private ParamType beParamType; 33 | 34 | public ParamDefinition() { 35 | super(); 36 | } 37 | 38 | public String getFeParamName() { 39 | return feParamName; 40 | } 41 | 42 | public void setFeParamName(String feParamName) { 43 | this.feParamName = feParamName; 44 | } 45 | 46 | public ParamType getFeParamType() { 47 | return feParamType; 48 | } 49 | 50 | public void setFeParamType(ParamType feParamType) { 51 | this.feParamType = feParamType; 52 | } 53 | 54 | public String getBeParamName() { 55 | return beParamName; 56 | } 57 | 58 | public void setBeParamName(String beParamName) { 59 | this.beParamName = beParamName; 60 | } 61 | 62 | public ParamType getBeParamType() { 63 | return beParamType; 64 | } 65 | 66 | public void setBeParamType(ParamType beParamType) { 67 | this.beParamType = beParamType; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/AppDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | public class AppDefinition { 19 | 20 | private Integer id; 21 | 22 | private String name; 23 | 24 | private Integer gwId; 25 | 26 | private String gwName; 27 | 28 | private String domain; 29 | 30 | private String prefix; 31 | 32 | public Integer getId() { 33 | return id; 34 | } 35 | 36 | public void setId(Integer id) { 37 | this.id = id; 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public void setName(String name) { 45 | this.name = name; 46 | } 47 | 48 | public Integer getGwId() { 49 | return gwId; 50 | } 51 | 52 | public void setGwId(Integer gwId) { 53 | this.gwId = gwId; 54 | } 55 | 56 | public String getDomain() { 57 | return domain; 58 | } 59 | 60 | public void setDomain(String domain) { 61 | this.domain = domain; 62 | } 63 | 64 | public String getPrefix() { 65 | return prefix; 66 | } 67 | 68 | public void setPrefix(String prefix) { 69 | this.prefix = prefix; 70 | } 71 | 72 | public String getGwName() { 73 | return gwName; 74 | } 75 | 76 | public void setGwName(String gwName) { 77 | this.gwName = gwName; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/ClusterDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | import java.util.LinkedList; 19 | import java.util.List; 20 | 21 | public class ClusterDefinition { 22 | 23 | private Integer id; 24 | 25 | private String code; 26 | 27 | private String name; 28 | 29 | private List instances = new LinkedList(); 30 | 31 | public Integer getId() { 32 | return id; 33 | } 34 | 35 | public void setId(Integer id) { 36 | this.id = id; 37 | } 38 | 39 | public String getCode() { 40 | return code; 41 | } 42 | 43 | public void setCode(String code) { 44 | this.code = code; 45 | } 46 | 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | public void setName(String name) { 52 | this.name = name; 53 | } 54 | 55 | public List getInstances() { 56 | return instances; 57 | } 58 | 59 | public void addInstance(InstanceDefinition instance) { 60 | if (instance != null) { 61 | this.instances.add(instance); 62 | } 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return "ClusterDefination [id=" + id + ", code=" + code + ", name=" + name + ", instances=" + instances + "]"; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/http/HttpClientTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.http; 17 | 18 | import io.vertx.core.Vertx; 19 | import io.vertx.core.VertxOptions; 20 | import io.vertx.core.http.HttpClient; 21 | import io.vertx.core.http.HttpClientOptions; 22 | import io.vertx.core.http.HttpHeaders; 23 | import io.vertx.core.http.HttpMethod; 24 | 25 | public class HttpClientTest { 26 | 27 | public static void main(String[] args) { 28 | Vertx vertx = Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(999999999)); 29 | 30 | HttpClientOptions options = new HttpClientOptions().setMaxPoolSize(1).setMaxWaitQueueSize(2); 31 | HttpClient client = vertx.createHttpClient(options); 32 | 33 | new Thread() { 34 | public void run() { 35 | client.request(HttpMethod.GET, "http://localhost:8081/hr/a").onSuccess(request -> { 36 | request.send().onSuccess(response -> { 37 | System.out.println(response.getHeader(HttpHeaders.CONTENT_LENGTH)); 38 | }); 39 | }).onFailure(t -> { 40 | System.out.println(Thread.currentThread().getName() + ": error is " + t); 41 | }); 42 | 43 | System.out.println("thread is over"); 44 | } 45 | 46 | }.start(); 47 | 48 | System.out.println("main is over"); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /agate-gateway/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logs 5 | detail.log 6 | error.log 7 | access.log 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/UserDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | public class UserDefinition { 19 | 20 | private Integer id; 21 | 22 | private int status; 23 | 24 | private String username; 25 | 26 | private String password; 27 | 28 | private String role; 29 | 30 | private String[] permissions; 31 | 32 | public Integer getId() { 33 | return id; 34 | } 35 | 36 | public void setId(Integer id) { 37 | this.id = id; 38 | } 39 | 40 | public int getStatus() { 41 | return status; 42 | } 43 | 44 | public void setStatus(int status) { 45 | this.status = status; 46 | } 47 | 48 | public String getUsername() { 49 | return username; 50 | } 51 | 52 | public void setUsername(String username) { 53 | this.username = username; 54 | } 55 | 56 | public String getPassword() { 57 | return password; 58 | } 59 | 60 | public void setPassword(String password) { 61 | this.password = password; 62 | } 63 | 64 | public String getRole() { 65 | return role; 66 | } 67 | 68 | public void setRole(String role) { 69 | this.role = role; 70 | } 71 | 72 | public String[] getPermissions() { 73 | return permissions; 74 | } 75 | 76 | public void setPermissions(String[] permissions) { 77 | this.permissions = permissions; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /agate-gateway/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logs 5 | detail.log 6 | error.log 7 | access.log 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/service/RandomLoadBalancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.service; 17 | 18 | import java.util.List; 19 | import java.util.concurrent.ThreadLocalRandom; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import io.agate.gateway.options.RouteOptions; 25 | 26 | public class RandomLoadBalancer implements Loadbalancer { 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(RandomLoadBalancer.class); 29 | 30 | private RouteOptions routeOptions; 31 | 32 | private ServiceAddressSupplier supplier; 33 | 34 | public RandomLoadBalancer(RouteOptions routeOptions, ServiceAddressSupplier supplier) { 35 | this.routeOptions = routeOptions; 36 | this.supplier = supplier; 37 | } 38 | 39 | @Override 40 | public String choose() { 41 | List serviceAddresses = supplier.get(); 42 | if (serviceAddresses.isEmpty()) { 43 | LOG.warn("No servers available for service: " + routeOptions.getRoute()); 44 | return null; 45 | } 46 | 47 | if (serviceAddresses.size() == 1) { 48 | return serviceAddresses.get(0).getUrl(); 49 | } 50 | 51 | int pos = ThreadLocalRandom.current().nextInt(serviceAddresses.size()); 52 | return serviceAddresses.get(pos % serviceAddresses.size()).getUrl(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/security/WebSecurityConfigurer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.security; 17 | 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 20 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 21 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 22 | import org.springframework.security.config.http.SessionCreationPolicy; 23 | 24 | 25 | @Configuration 26 | public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter { 27 | 28 | @Override 29 | public void configure(WebSecurity web) throws Exception { 30 | super.configure(web); 31 | } 32 | 33 | @Override 34 | protected void configure(HttpSecurity http) throws Exception { 35 | http.cors().and().csrf().disable().formLogin().disable().httpBasic().disable() 36 | .authorizeRequests().antMatchers("/cluster/**", "/gateway/**", "/apps/**", "/route/**").authenticated() 37 | .anyRequest().permitAll() 38 | // 设置Session的创建策略为:Spring Security永不创建HttpSession 不使用HttpSession来获取SecurityContext 39 | .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 40 | .and().addFilter(new JwtAuthenticationFilter(authenticationManager())); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Descriptions-e6f4f0ea.js: -------------------------------------------------------------------------------- 1 | import{b as e,y as a,d as l,q as t,r as s,e as r,a0 as o,a2 as i,ai as d,a6 as n,aj as c,a as f,ak as u,al as p,a9 as b,ac as m,j as v,_ as x}from"./index-5b8751dc.js";/* empty css */const g=e(),h=a((()=>g.getMobile)),{getPrefixCls:y}=v(),_=y("descriptions"),j=x(l({name:"Descriptions",props:{title:t.string.def(""),message:t.string.def(""),collapse:t.bool.def(!0),border:t.bool.def(!0),column:t.number.def(2),size:t.oneOf(["large","default","small"]).def("default"),direction:t.oneOf(["horizontal","vertical"]).def("horizontal"),extra:t.string.def(""),schema:{type:Array,default:()=>[]},data:{type:Object,default:()=>({})}},setup(e,{slots:l,attrs:t}){const v=a((()=>{const a=["title","message","collapse","schema","data","class"],l={...t,...e};for(const e in l)-1!==a.indexOf(e)&&delete l[e];return f(h)&&(l.direction="vertical"),l})),x=s(!0),g=()=>{e.collapse&&(x.value=!f(x))};return()=>r("div",{class:[_,"bg-[var(--el-color-white)] dark:bg-[var(--el-bg-color)] dark:border-[var(--el-border-color)] dark:border-1px"]},[e.title?r("div",{class:[`${_}-header`,"relative h-50px flex justify-between items-center layout-border__bottom px-10px cursor-pointer"],onClick:g},[r("div",{class:[`${_}-header__title`,"relative font-18px font-bold ml-10px"]},[r("div",{class:"flex items-center"},[e.title,e.message?r(o,{content:e.message,placement:"right"},{default:()=>[r(i,{icon:"bi:question-circle-fill",class:"ml-5px",size:14},null)]}):null])]),e.collapse?r(i,{icon:x.value?"ep:arrow-down":"ep:arrow-up"},null):null]):null,r(d,null,{default:()=>[n(r("div",{class:[`${_}-content`,""]},[r(u,f(v),{extra:()=>l.extra?l.extra():e.extra,default:()=>e.schema.map((a=>r(p,b({key:a.field},(e=>{const a=["field"],l={...e};for(const t in l)-1!==a.indexOf(t)&&delete l[t];return l})(a)),{label:()=>{var e,l;return(null==(e=a.slots)?void 0:e.label)?null==(l=a.slots)?void 0:l.label(a):a.label},default:()=>{var l,t;return(null==(l=a.slots)?void 0:l.default)?null==(t=a.slots)?void 0:t.default(e.data):m(e.data,a.field)}})))})]),[[c,f(x)]])]})])}}),[["__scopeId","data-v-9fa1bfd1"]]);export{j as D}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/verticle/SystemVerticle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.verticle; 17 | 18 | import io.agate.gateway.context.AddressConstant; 19 | import io.agate.gateway.context.ApplicationContext; 20 | import io.vertx.core.AbstractVerticle; 21 | import io.vertx.core.Context; 22 | import io.vertx.core.Promise; 23 | import io.vertx.core.Vertx; 24 | import io.vertx.micrometer.MetricsService; 25 | 26 | /** 27 | * collect system runtime parameters. 28 | * 29 | * @author dinstone 30 | */ 31 | public class SystemVerticle extends AbstractVerticle { 32 | 33 | private MetricsService metricsService; 34 | 35 | public SystemVerticle(ApplicationContext context) { 36 | } 37 | 38 | @Override 39 | public void init(Vertx vertx, Context context) { 40 | super.init(vertx, context); 41 | 42 | metricsService = MetricsService.create(vertx); 43 | } 44 | 45 | @Override 46 | public void start(Promise startPromise) throws Exception { 47 | vertx.eventBus().consumer(AddressConstant.APM_METRICS, message -> { 48 | if (message.body() instanceof String) { 49 | String baseName = (String) message.body(); 50 | message.reply(metricsService.getMetricsSnapshot(baseName)); 51 | } else { 52 | message.reply(metricsService.getMetricsSnapshot()); 53 | } 54 | }); 55 | 56 | startPromise.complete(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/http/QueryCoderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.http; 17 | 18 | import static org.junit.jupiter.api.Assertions.assertEquals; 19 | import static org.junit.jupiter.api.Assertions.assertNotEquals; 20 | import static org.junit.jupiter.api.Assertions.assertNotNull; 21 | import static org.junit.jupiter.api.Assertions.assertTrue; 22 | 23 | import org.junit.jupiter.api.Test; 24 | 25 | import io.agate.gateway.http.QueryCoder; 26 | 27 | class QueryCoderTest { 28 | 29 | @Test 30 | void testAddParam() { 31 | String u = "http://localhost:5256/static/:path?pa=12&pa=34&pb=afasdf"; 32 | QueryCoder qc = new QueryCoder(u); 33 | qc.addParam("pa", "56"); 34 | 35 | String uri = qc.uri(); 36 | assertNotNull(uri); 37 | assertTrue(uri.startsWith("http://localhost:5256")); 38 | assertTrue(uri.contains("pa=56")); 39 | assertTrue(uri.contains("pa=12")); 40 | } 41 | 42 | @Test 43 | void testUri() { 44 | String u = "http://localhost:5256/static/:path"; 45 | QueryCoder qc = new QueryCoder(u); 46 | 47 | assertEquals(qc.uri(), qc.raw()); 48 | } 49 | 50 | @Test 51 | void testRaw() { 52 | String u = "http://localhost:5256/static/:path?pa=12&pa=34&pb=afasdf"; 53 | QueryCoder qc = new QueryCoder(u); 54 | 55 | assertNotEquals(qc.uri(), qc.raw()); 56 | assertEquals(u, qc.raw()); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/service/RoundRobinLoadBalancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.service; 17 | 18 | import java.util.List; 19 | import java.util.concurrent.atomic.AtomicInteger; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import io.agate.gateway.options.RouteOptions; 25 | 26 | public class RoundRobinLoadBalancer implements Loadbalancer { 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(RoundRobinLoadBalancer.class); 29 | 30 | private AtomicInteger position = new AtomicInteger(); 31 | 32 | private RouteOptions routeOptions; 33 | 34 | private ServiceAddressSupplier supplier; 35 | 36 | public RoundRobinLoadBalancer(RouteOptions routeOptions, ServiceAddressSupplier supplier) { 37 | this.routeOptions = routeOptions; 38 | this.supplier = supplier; 39 | } 40 | 41 | @Override 42 | public String choose() { 43 | List serviceAddresses = supplier.get(); 44 | if (serviceAddresses.isEmpty()) { 45 | LOG.warn("No available servers for route: " + routeOptions.getRoute()); 46 | return null; 47 | } 48 | 49 | if (serviceAddresses.size() == 1) { 50 | return serviceAddresses.get(0).getUrl(); 51 | } 52 | 53 | int pos = Math.abs(this.position.getAndIncrement()); 54 | return serviceAddresses.get(pos % serviceAddresses.size()).getUrl(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/InstanceDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | import java.util.Objects; 19 | 20 | public class InstanceDefinition { 21 | 22 | private String clusterCode; 23 | 24 | private String instanceId; 25 | 26 | private String manageHost; 27 | 28 | private int managePort; 29 | 30 | public String getInstanceId() { 31 | return instanceId; 32 | } 33 | 34 | public void setInstanceId(String instanceId) { 35 | this.instanceId = instanceId; 36 | } 37 | 38 | public String getClusterCode() { 39 | return clusterCode; 40 | } 41 | 42 | public void setClusterCode(String clusterCode) { 43 | this.clusterCode = clusterCode; 44 | } 45 | 46 | public String getManageHost() { 47 | return manageHost; 48 | } 49 | 50 | public void setManageHost(String manageHost) { 51 | this.manageHost = manageHost; 52 | } 53 | 54 | public int getManagePort() { 55 | return managePort; 56 | } 57 | 58 | public void setManagePort(int managePort) { 59 | this.managePort = managePort; 60 | } 61 | 62 | @Override 63 | public int hashCode() { 64 | return Objects.hash(instanceId); 65 | } 66 | 67 | @Override 68 | public boolean equals(Object obj) { 69 | if (this == obj) 70 | return true; 71 | if (obj == null) 72 | return false; 73 | if (getClass() != obj.getClass()) 74 | return false; 75 | InstanceDefinition other = (InstanceDefinition) obj; 76 | return Objects.equals(instanceId, other.instanceId); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/DateFormatTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | import java.text.DateFormat; 19 | import java.text.SimpleDateFormat; 20 | import java.time.Instant; 21 | import java.time.ZoneId; 22 | import java.time.ZonedDateTime; 23 | import java.time.format.DateTimeFormatter; 24 | import java.util.Date; 25 | 26 | public class DateFormatTest { 27 | public static void main(String[] args) { 28 | long timestamp = new Date().getTime(); 29 | 30 | tdate(timestamp); 31 | ndate(timestamp); 32 | } 33 | 34 | private static void tdate(long timestamp) { 35 | DateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); 36 | 37 | long s = System.currentTimeMillis(); 38 | for (int i = 0; i < 10000; i++) { 39 | String ts = dateTimeFormat.format(new Date(timestamp)); 40 | } 41 | long e = System.currentTimeMillis(); 42 | 43 | System.out.println("tdate is " + (e - s)); 44 | } 45 | 46 | private static void ndate(long timestamp) { 47 | DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS"); 48 | ZonedDateTime atZone = Instant.ofEpochMilli(timestamp).atZone(ZoneId.of("GMT")); 49 | long s = System.currentTimeMillis(); 50 | for (int i = 0; i < 10000; i++) { 51 | String ts = f.format(atZone); 52 | // String ts = Utils.formatRFC1123DateTime(timestamp); 53 | } 54 | long e = System.currentTimeMillis(); 55 | 56 | System.out.println("ndate is " + (e - s)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/el-popper-cecd0dcb.css: -------------------------------------------------------------------------------- 1 | .el-popper{--el-popper-border-radius:var(--el-popover-border-radius,4px);border-radius:var(--el-popper-border-radius);font-size:12px;line-height:20px;min-width:10px;overflow-wrap:break-word;padding:5px 11px;position:absolute;visibility:visible;z-index:2000}.el-popper.is-dark{background:var(--el-text-color-primary);border:1px solid var(--el-text-color-primary);color:var(--el-bg-color)}.el-popper.is-dark .el-popper__arrow:before{background:var(--el-text-color-primary);border:1px solid var(--el-text-color-primary);right:0}.el-popper.is-light{background:var(--el-bg-color-overlay);border:1px solid var(--el-border-color-light)}.el-popper.is-light .el-popper__arrow:before{background:var(--el-bg-color-overlay);border:1px solid var(--el-border-color-light);right:0}.el-popper.is-pure{padding:0}.el-popper__arrow{height:10px;position:absolute;width:10px;z-index:-1}.el-popper__arrow:before{background:var(--el-text-color-primary);box-sizing:border-box;content:" ";height:10px;position:absolute;transform:rotate(45deg);width:10px;z-index:-1}.el-popper[data-popper-placement^=top]>.el-popper__arrow{bottom:-5px}.el-popper[data-popper-placement^=top]>.el-popper__arrow:before{border-bottom-right-radius:2px}.el-popper[data-popper-placement^=bottom]>.el-popper__arrow{top:-5px}.el-popper[data-popper-placement^=bottom]>.el-popper__arrow:before{border-top-left-radius:2px}.el-popper[data-popper-placement^=left]>.el-popper__arrow{right:-5px}.el-popper[data-popper-placement^=left]>.el-popper__arrow:before{border-top-right-radius:2px}.el-popper[data-popper-placement^=right]>.el-popper__arrow{left:-5px}.el-popper[data-popper-placement^=right]>.el-popper__arrow:before{border-bottom-left-radius:2px}.el-popper[data-popper-placement^=top] .el-popper__arrow:before{border-left-color:transparent!important;border-top-color:transparent!important}.el-popper[data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent!important;border-right-color:transparent!important}.el-popper[data-popper-placement^=left] .el-popper__arrow:before{border-bottom-color:transparent!important;border-left-color:transparent!important}.el-popper[data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent!important;border-top-color:transparent!important} 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/api/AuthenResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.api; 17 | 18 | import javax.servlet.http.HttpServletResponse; 19 | 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.web.bind.annotation.PostMapping; 22 | import org.springframework.web.bind.annotation.PutMapping; 23 | import org.springframework.web.bind.annotation.RequestBody; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.RestController; 26 | 27 | import io.agate.admin.business.BusinessException; 28 | import io.agate.admin.business.model.UserDefinition; 29 | import io.agate.admin.business.service.AuthenService; 30 | import io.agate.admin.utils.JwtUtil; 31 | 32 | @RestController 33 | @RequestMapping("/authen") 34 | public class AuthenResource { 35 | 36 | @Autowired 37 | private AuthenService authenService; 38 | 39 | @PostMapping("/login") 40 | public UserDefinition login(@RequestBody UserDefinition user, HttpServletResponse response) throws BusinessException { 41 | UserDefinition ud = authenService.authen(user.getUsername(), user.getPassword()); 42 | 43 | String token = JwtUtil.createToken(ud.getUsername(), ud.getRole()); 44 | String bearerToken = JwtUtil.TOKEN_PREFIX + token; 45 | response.addHeader(JwtUtil.TOKEN_HEADER, bearerToken); 46 | 47 | ud.setPassword(bearerToken); 48 | return ud; 49 | } 50 | 51 | @PutMapping("/logout") 52 | public boolean logout(String username) throws BusinessException { 53 | return true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/LocaleDropdown.vue_vue_type_script_setup_true_lang-f77fc5b1.js: -------------------------------------------------------------------------------- 1 | import{d as a,b as o,r as e,o as s,i as l,n,a as c,aN as t,j as r,_ as i,aT as m,aU as p,aV as u,aW as d,aX as g,q as _,aY as f,y as j,B as v,w as L,e as h,c as w,L as C,K as b,a4 as I,a3 as D,a5 as V,J as k,t as x}from"./index-5b8751dc.js";import"./useForm-95be4c91.js";import{u as y}from"./useIcon-f4304df6.js";/* empty css *//* empty css *//* empty css */import"./tsxHelper-11a4c46e.js";const E="/assets/logo-bd01a334.png",T="var(--el-color-black)",z=i(a({__name:"ThemeSwitch",setup(a){const{getPrefixCls:i}=r(),m=i("theme-switch"),p=y({icon:"emojione-monotone:sun",color:"#fde047"}),u=y({icon:"emojione-monotone:crescent-moon",color:"#fde047"}),d=o(),g=e(d.getIsDark),_=a=>{d.setIsDark(a)};return(a,o)=>(s(),l(c(t),{class:n(c(m)),modelValue:g.value,"onUpdate:modelValue":o[0]||(o[0]=a=>g.value=a),"inline-prompt":"","border-color":T,"inactive-color":T,"active-color":T,"active-icon":c(p),"inactive-icon":c(u),onChange:_},null,8,["class","modelValue","active-icon","inactive-icon"]))}}),[["__scopeId","data-v-e70fc6a8"]]),P=()=>({changeLocale:async a=>{const o=m.global,e=await p(Object.assign({"../../locales/en.ts":()=>u((()=>import("./en-c5b47d83.js")),[]),"../../locales/zh-CN.ts":()=>u((()=>import("./zh-CN-423bc1c6.js")),[])}),`../../locales/${a}.ts`);o.setLocaleMessage(a,e.default),(a=>{const o=d();"legacy"===m.mode?m.global.locale=a:m.global.locale.value=a,o.setCurrentLocale({lang:a}),g(a)})(a)}}),N=a({__name:"LocaleDropdown",props:{color:_.string.def("")},setup(a){const{getPrefixCls:o}=r(),e=o("locale-dropdown"),t=f(),i=j((()=>t.getLocaleMap)),m=j((()=>t.getCurrentLocale)),p=a=>{if(a===c(m).lang)return;window.location.reload(),t.setCurrentLocale({lang:a});const{changeLocale:o}=P();o(a)};return(o,t)=>{const r=v("Icon");return s(),l(c(D),{class:n(c(e)),trigger:"click",onCommand:p},{dropdown:L((()=>[h(c(I),null,{default:L((()=>[(s(!0),w(b,null,C(i.value,(a=>(s(),l(c(V),{key:a.lang,command:a.lang},{default:L((()=>[k(x(a.name),1)])),_:2},1032,["command"])))),128))])),_:1})])),default:L((()=>[h(r,{size:18,icon:"ion:language-sharp",class:n(["cursor-pointer !p-0",o.$attrs.class]),color:a.color},null,8,["class","color"])])),_:1},8,["class"])}}});export{z as T,N as _,E as a}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/RegisterForm.vue_vue_type_script_setup_true_lang-73f185cd.js: -------------------------------------------------------------------------------- 1 | import{u as e,F as o}from"./useForm-95be4c91.js";import{d as s,s as l,e as r,an as a,O as t,K as n,r as d,o as i,i as c,a as p,R as m,k as u}from"./index-5b8751dc.js";/* empty css */import"./tsxHelper-11a4c46e.js";import{u as f}from"./useValidator-0a43379b.js";function g(e){return"function"==typeof e||"[object Object]"===Object.prototype.toString.call(e)&&!m(e)}const h=s({__name:"RegisterForm",emits:["to-login"],setup(s,{emit:m}){const{formRegister:h,formMethods:w}=e(),{getElFormExpose:P}=w,{t:b}=u(),{required:v}=f(),y=l([{field:"title",colProps:{span:24},formItemProps:{slots:{default:()=>r("h2",{class:"text-2xl font-bold text-center w-[100%]"},[b("login.register")])}}},{field:"username",label:b("login.username"),value:"",component:"Input",colProps:{span:24},componentProps:{placeholder:b("login.usernamePlaceholder")}},{field:"password",label:b("login.password"),value:"",component:"InputPassword",colProps:{span:24},componentProps:{style:{width:"100%"},strength:!0,placeholder:b("login.passwordPlaceholder")}},{field:"check_password",label:b("login.checkPassword"),value:"",component:"InputPassword",colProps:{span:24},componentProps:{style:{width:"100%"},strength:!0,placeholder:b("login.passwordPlaceholder")}},{field:"code",label:b("login.code"),colProps:{span:24},formItemProps:{slots:{default:e=>r("div",{class:"w-[100%] flex"},[r(a,{modelValue:e.code,"onUpdate:modelValue":o=>e.code=o,placeholder:b("login.codePlaceholder")},null)])}}},{field:"register",colProps:{span:24},formItemProps:{slots:{default:()=>{let e,o;return r(n,null,[r("div",{class:"w-[100%]"},[r(t,{type:"primary",class:"w-[100%]",loading:j.value,onClick:I},g(e=b("login.register"))?e:{default:()=>[e]})]),r("div",{class:"w-[100%] mt-15px"},[r(t,{class:"w-[100%]",onClick:x},g(o=b("login.hasUser"))?o:{default:()=>[o]})])])}}}}]),k={username:[v()],password:[v()],check_password:[v()],code:[v()]},x=()=>{m("to-login")},j=d(!1),I=async()=>{const e=await P();null==e||e.validate((async e=>{if(e)try{j.value=!0,x()}finally{j.value=!1}}))};return(e,s)=>(i(),c(p(o),{schema:y,rules:k,"label-position":"top","hide-required-asterisk":"",size:"large",class:"dark:border-1 dark:border-[var(--el-border-color)] dark:border-solid",onRegister:p(h)},null,8,["schema","onRegister"]))}});export{h as _}; 2 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/RedisTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | import io.vertx.core.Vertx; 19 | import io.vertx.redis.client.Command; 20 | import io.vertx.redis.client.Redis; 21 | import io.vertx.redis.client.Request; 22 | 23 | import java.io.IOException; 24 | 25 | public class RedisTest { 26 | public static void main(String[] args) throws IOException { 27 | String script = buildLuaScript(); 28 | Vertx vertx = Vertx.vertx(); 29 | Redis.createClient( 30 | vertx, 31 | "redis://localhost:6379") 32 | .connect() 33 | .onSuccess(conn -> { 34 | // use the connection 35 | long ts = System.currentTimeMillis(); 36 | conn.send(Request.cmd(Command.EVAL, script, 1, "limit:liziba:view", ts, ts - 3000, 5)).onSuccess(r -> { 37 | System.out.println(r); 38 | }).onFailure(e -> e.printStackTrace()); 39 | }); 40 | 41 | System.in.read(); 42 | 43 | vertx.close(); 44 | } 45 | 46 | private static String buildLuaScript() { 47 | return "redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, tonumber(ARGV[2])) \n" + 48 | "local c = redis.call('ZCARD', KEYS[1]) \n" + 49 | "if c < tonumber(ARGV[3]) \n" + 50 | "then \n" + 51 | " redis.call('ZADD', KEYS[1], tonumber(ARGV[1]), ARGV[1]) \n" + 52 | " return c+1 \n" + 53 | "else \n" + 54 | " return 0 \n" + 55 | "end \n"; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/api/ClusterResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.api; 17 | 18 | import java.util.List; 19 | 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.web.bind.annotation.DeleteMapping; 22 | import org.springframework.web.bind.annotation.GetMapping; 23 | import org.springframework.web.bind.annotation.PostMapping; 24 | import org.springframework.web.bind.annotation.RequestBody; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | import org.springframework.web.bind.annotation.RestController; 27 | 28 | import io.agate.admin.business.BusinessException; 29 | import io.agate.admin.business.model.ClusterDefinition; 30 | import io.agate.admin.business.service.ClusterService; 31 | 32 | @RestController 33 | @RequestMapping("/cluster") 34 | public class ClusterResource { 35 | 36 | @Autowired 37 | private ClusterService clusterService; 38 | 39 | @GetMapping("/list") 40 | public List list() { 41 | return clusterService.clusterList(); 42 | } 43 | 44 | @PostMapping("/save") 45 | public boolean save(@RequestBody ClusterDefinition clusterDefinition) throws BusinessException { 46 | if (clusterDefinition.getId() == null) { 47 | clusterService.createCluster(clusterDefinition); 48 | } else { 49 | clusterService.updateCluster(clusterDefinition); 50 | } 51 | return true; 52 | } 53 | 54 | @DeleteMapping("/delete") 55 | public boolean delete(@RequestBody Integer[] ids) throws BusinessException { 56 | if (ids != null) { 57 | for (Integer id : ids) { 58 | clusterService.deleteCluster(id); 59 | } 60 | } 61 | return true; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/repository/entity/AppEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.repository.entity; 17 | 18 | import java.util.Date; 19 | 20 | public class AppEntity { 21 | 22 | private Integer id; 23 | 24 | private String name; 25 | 26 | private Integer gwId; 27 | 28 | private String gwName; 29 | 30 | private String json; 31 | 32 | private Date createTime; 33 | 34 | private Date updateTime; 35 | 36 | public Integer getId() { 37 | return id; 38 | } 39 | 40 | public void setId(Integer id) { 41 | this.id = id; 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | public Integer getGwId() { 53 | return gwId; 54 | } 55 | 56 | public void setGwId(Integer gwId) { 57 | this.gwId = gwId; 58 | } 59 | 60 | public String getJson() { 61 | return json; 62 | } 63 | 64 | public void setJson(String json) { 65 | this.json = json; 66 | } 67 | 68 | public Date getCreateTime() { 69 | return createTime; 70 | } 71 | 72 | public void setCreateTime(Date createTime) { 73 | this.createTime = createTime; 74 | } 75 | 76 | public Date getUpdateTime() { 77 | return updateTime; 78 | } 79 | 80 | public void setUpdateTime(Date updateTime) { 81 | this.updateTime = updateTime; 82 | } 83 | 84 | public String getGwName() { 85 | return gwName; 86 | } 87 | 88 | public void setGwName(String gwName) { 89 | this.gwName = gwName; 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | return "AppEntity [id=" + id + ", name=" + name + ", gwId=" + gwId + ", json=" + json + ", createTime=" 95 | + createTime + ", updateTime=" + updateTime + "]"; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/repository/entity/GatewayEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.repository.entity; 17 | 18 | import java.util.Date; 19 | 20 | public class GatewayEntity { 21 | 22 | private String ccode; 23 | 24 | private String cname; 25 | 26 | private Integer id; 27 | 28 | private String name; 29 | 30 | private int status; 31 | 32 | private String json; 33 | 34 | private Date createTime; 35 | 36 | private Date updateTime; 37 | 38 | public String getCcode() { 39 | return ccode; 40 | } 41 | 42 | public void setCcode(String ccode) { 43 | this.ccode = ccode; 44 | } 45 | 46 | public String getCname() { 47 | return cname; 48 | } 49 | 50 | public void setCname(String cname) { 51 | this.cname = cname; 52 | } 53 | 54 | public Integer getId() { 55 | return id; 56 | } 57 | 58 | public void setId(Integer id) { 59 | this.id = id; 60 | } 61 | 62 | public String getName() { 63 | return name; 64 | } 65 | 66 | public void setName(String name) { 67 | this.name = name; 68 | } 69 | 70 | public int getStatus() { 71 | return status; 72 | } 73 | 74 | public void setStatus(int status) { 75 | this.status = status; 76 | } 77 | 78 | public String getJson() { 79 | return json; 80 | } 81 | 82 | public void setJson(String json) { 83 | this.json = json; 84 | } 85 | 86 | public Date getCreateTime() { 87 | return createTime; 88 | } 89 | 90 | public void setCreateTime(Date createTime) { 91 | this.createTime = createTime; 92 | } 93 | 94 | public Date getUpdateTime() { 95 | return updateTime; 96 | } 97 | 98 | public void setUpdateTime(Date updateTime) { 99 | this.updateTime = updateTime; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/handler/internal/RateLimitHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.handler.internal; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import io.agate.gateway.handler.OrderedHandler; 22 | import io.agate.gateway.options.RouteOptions; 23 | import io.agate.gateway.plugin.PluginOptions; 24 | import io.vertx.core.Vertx; 25 | import io.vertx.ext.web.RoutingContext; 26 | import io.vertx.ext.web.handler.HttpException; 27 | 28 | /** 29 | * rate limit handler. 30 | * 31 | * @author dinstone 32 | */ 33 | public class RateLimitHandler extends OrderedHandler { 34 | 35 | private static final Logger LOG = LoggerFactory.getLogger(RateLimitHandler.class); 36 | 37 | private final RedisRateLimiter rateLimiter; 38 | 39 | public RateLimitHandler(Vertx vertx, RouteOptions routeOptions, PluginOptions pluginOptions) { 40 | super(400); 41 | 42 | this.rateLimiter = new RedisRateLimiter(vertx, routeOptions.getRoute(), pluginOptions.getOptions()); 43 | } 44 | 45 | @Override 46 | public void destroy() { 47 | if (rateLimiter != null) { 48 | rateLimiter.destroy(); 49 | } 50 | } 51 | 52 | @Override 53 | public void handle(RoutingContext rc) { 54 | rateLimiter.acquire().onSuccess(b -> { 55 | if (b) { 56 | rc.next(); 57 | } else { 58 | rc.fail(new HttpException(429, "too many requests, rate limit " + rateLimiter.getCount() + "/" + rateLimiter.getPeriod())); 59 | } 60 | }).onFailure(e -> { 61 | LOG.warn(rateLimiter.getLimitName() + " rate limit error", e); 62 | rc.fail(new HttpException(429, "rate limit error: " + e.getMessage())); 63 | }); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/api/AppsResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.api; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.web.bind.annotation.DeleteMapping; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PostMapping; 22 | import org.springframework.web.bind.annotation.RequestBody; 23 | import org.springframework.web.bind.annotation.RequestMapping; 24 | import org.springframework.web.bind.annotation.RestController; 25 | 26 | import io.agate.admin.business.BusinessException; 27 | import io.agate.admin.business.model.AppDefinition; 28 | import io.agate.admin.business.param.AppDetail; 29 | import io.agate.admin.business.param.PageList; 30 | import io.agate.admin.business.param.PageQuery; 31 | import io.agate.admin.business.service.ManageService; 32 | 33 | @RestController 34 | @RequestMapping("/apps") 35 | public class AppsResource { 36 | 37 | @Autowired 38 | private ManageService manageService; 39 | 40 | @GetMapping("/list") 41 | public PageList list(PageQuery query) { 42 | return manageService.appList(query); 43 | } 44 | 45 | @GetMapping("/detail") 46 | public AppDetail detail(Integer id) { 47 | return manageService.getAppById(id); 48 | } 49 | 50 | @PostMapping("/save") 51 | public boolean add(@RequestBody AppDefinition appDefinition) throws BusinessException { 52 | if (appDefinition.getId() == null) { 53 | manageService.createApp(appDefinition); 54 | } else { 55 | manageService.updateApp(appDefinition); 56 | } 57 | return true; 58 | } 59 | 60 | @DeleteMapping("/delete") 61 | public boolean add(@RequestBody Integer[] ids) throws BusinessException { 62 | if (ids != null) { 63 | for (Integer id : ids) { 64 | manageService.deleteApp(id); 65 | } 66 | } 67 | return true; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/handler/internal/MeterMetricsHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.handler.internal; 17 | 18 | import java.util.Arrays; 19 | import java.util.List; 20 | 21 | import io.agate.gateway.handler.OrderedHandler; 22 | import io.agate.gateway.options.RouteOptions; 23 | import io.micrometer.core.instrument.Counter; 24 | import io.micrometer.core.instrument.MeterRegistry; 25 | import io.micrometer.core.instrument.Tag; 26 | import io.micrometer.core.instrument.Timer; 27 | import io.micrometer.core.instrument.Timer.Sample; 28 | import io.vertx.ext.web.RoutingContext; 29 | import io.vertx.micrometer.backends.BackendRegistries; 30 | 31 | public class MeterMetricsHandler extends OrderedHandler { 32 | 33 | private Counter count; 34 | 35 | private Counter error; 36 | 37 | private Timer timer; 38 | 39 | public MeterMetricsHandler(RouteOptions routeOptions) { 40 | super(100); 41 | 42 | MeterRegistry meterRegistry = BackendRegistries.getDefaultNow(); 43 | 44 | List tags = Arrays.asList(Tag.of("gateway", routeOptions.getGateway())); 45 | this.count = meterRegistry.counter(routeOptions.getRoute() + "_count", tags); 46 | this.error = meterRegistry.counter(routeOptions.getRoute() + "_error", tags); 47 | this.timer = meterRegistry.timer(routeOptions.getRoute() + "_time", tags); 48 | } 49 | 50 | @Override 51 | public void handle(RoutingContext context) { 52 | Sample sample = Timer.start(); 53 | context.addBodyEndHandler(v -> { 54 | sample.stop(timer); 55 | 56 | count.increment(); 57 | if (isErrorCode(context.response().getStatusCode())) { 58 | error.increment(); 59 | } 60 | }); 61 | context.next(); 62 | } 63 | 64 | private boolean isErrorCode(int statusCode) { 65 | return statusCode < 200 || statusCode >= 400; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/repository/entity/RouteEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.repository.entity; 17 | 18 | import java.util.Date; 19 | 20 | public class RouteEntity { 21 | 22 | private Integer id; 23 | 24 | private Integer appId; 25 | 26 | private String appName; 27 | 28 | private String name; 29 | 30 | private int status; 31 | 32 | private String json; 33 | 34 | private Date createTime; 35 | 36 | private Date updateTime; 37 | 38 | public Integer getId() { 39 | return id; 40 | } 41 | 42 | public void setId(Integer id) { 43 | this.id = id; 44 | } 45 | 46 | public Integer getAppId() { 47 | return appId; 48 | } 49 | 50 | public void setAppId(Integer appId) { 51 | this.appId = appId; 52 | } 53 | 54 | public String getName() { 55 | return name; 56 | } 57 | 58 | public void setName(String name) { 59 | this.name = name; 60 | } 61 | 62 | public int getStatus() { 63 | return status; 64 | } 65 | 66 | public void setStatus(int status) { 67 | this.status = status; 68 | } 69 | 70 | public String getJson() { 71 | return json; 72 | } 73 | 74 | public void setJson(String json) { 75 | this.json = json; 76 | } 77 | 78 | public Date getCreateTime() { 79 | return createTime; 80 | } 81 | 82 | public void setCreateTime(Date createTime) { 83 | this.createTime = createTime; 84 | } 85 | 86 | public Date getUpdateTime() { 87 | return updateTime; 88 | } 89 | 90 | public void setUpdateTime(Date updateTime) { 91 | this.updateTime = updateTime; 92 | } 93 | 94 | public String getAppName() { 95 | return appName; 96 | } 97 | 98 | public void setAppName(String appName) { 99 | this.appName = appName; 100 | } 101 | 102 | @Override 103 | public String toString() { 104 | return "RouteEntity [id=" + id + ", appId=" + appId + ", name=" + name + ", status=" + status + ", json=" + json 105 | + ", createTime=" + createTime + ", updateTime=" + updateTime + "]"; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /agate-gateway/src/test/java/io/agate/gateway/Trie.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway; 17 | 18 | public class Trie { 19 | 20 | private TrieNode root; 21 | 22 | public Trie() { 23 | root = new TrieNode(); 24 | } 25 | 26 | // Inserts a word into the trie. 27 | public void insert(String word) { 28 | TrieNode node = root; 29 | for (int i = 0; i < word.length(); i++) { 30 | char currentChar = word.charAt(i); 31 | if (!node.containsKey(currentChar)) { 32 | node.put(currentChar, new TrieNode()); 33 | } 34 | node = node.get(currentChar); 35 | } 36 | node.setEnd(); 37 | } 38 | 39 | // search a prefix or whole key in trie and 40 | // returns the node where search ends 41 | private TrieNode searchPrefix(String word) { 42 | TrieNode node = root; 43 | for (int i = 0; i < word.length(); i++) { 44 | char curLetter = word.charAt(i); 45 | if (node.containsKey(curLetter)) { 46 | node = node.get(curLetter); 47 | } else { 48 | return null; 49 | } 50 | } 51 | return node; 52 | } 53 | 54 | // Returns if the word is in the trie. 55 | public boolean search(String word) { 56 | TrieNode node = searchPrefix(word); 57 | return node != null && node.isEnd(); 58 | } 59 | 60 | // Returns if there is any word in the trie 61 | // that starts with the given prefix. 62 | public boolean startsWith(String prefix) { 63 | TrieNode node = searchPrefix(prefix); 64 | return node != null; 65 | } 66 | } 67 | 68 | class TrieNode { 69 | 70 | // R links to node children 71 | private TrieNode[] links; 72 | 73 | private final int R = 26; 74 | 75 | private boolean isEnd; 76 | 77 | public TrieNode() { 78 | links = new TrieNode[R]; 79 | } 80 | 81 | public boolean containsKey(char ch) { 82 | return links[ch - 'a'] != null; 83 | } 84 | 85 | public TrieNode get(char ch) { 86 | return links[ch - 'a']; 87 | } 88 | 89 | public void put(char ch, TrieNode node) { 90 | links[ch - 'a'] = node; 91 | } 92 | 93 | public void setEnd() { 94 | isEnd = true; 95 | } 96 | 97 | public boolean isEnd() { 98 | return isEnd; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/AgateAdminListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin; 17 | 18 | import java.util.concurrent.Executors; 19 | import java.util.concurrent.ScheduledExecutorService; 20 | import java.util.concurrent.ThreadFactory; 21 | import java.util.concurrent.TimeUnit; 22 | 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.boot.context.event.ApplicationStartedEvent; 27 | import org.springframework.context.ApplicationListener; 28 | import org.springframework.stereotype.Component; 29 | 30 | import io.agate.admin.business.service.ClusterService; 31 | import io.agate.admin.business.service.ManageService; 32 | 33 | @Component 34 | public class AgateAdminListener implements ApplicationListener { 35 | 36 | private static final Logger LOG = LoggerFactory.getLogger(AgateAdminListener.class); 37 | 38 | @Autowired 39 | private ClusterService clusterService; 40 | 41 | @Autowired 42 | private ManageService manageService; 43 | 44 | private ScheduledExecutorService executor; 45 | 46 | @Override 47 | public void onApplicationEvent(ApplicationStartedEvent event) { 48 | executor = Executors.newScheduledThreadPool(1, new ThreadFactory() { 49 | 50 | @Override 51 | public Thread newThread(Runnable r) { 52 | Thread thread = new Thread(r, "agate-admin-context"); 53 | thread.setDaemon(true); 54 | return thread; 55 | } 56 | }); 57 | executor.scheduleAtFixedRate(new Runnable() { 58 | 59 | @Override 60 | public void run() { 61 | try { 62 | clusterService.clusterRefresh(); 63 | } catch (Exception e) { 64 | LOG.error("agate gateway cluster discovery error: {}", e.getMessage()); 65 | } 66 | } 67 | }, 1, 3, TimeUnit.SECONDS); 68 | 69 | executor.scheduleWithFixedDelay(new Runnable() { 70 | 71 | @Override 72 | public void run() { 73 | try { 74 | manageService.gatewayRefresh(); 75 | } catch (Exception e) { 76 | LOG.error("agate gateway instance refresh error: {}", e.getMessage()); 77 | } 78 | } 79 | }, 3, 5, TimeUnit.SECONDS); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/GatewayDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | public class GatewayDefinition { 19 | 20 | private Integer id; 21 | 22 | private String ccode; 23 | 24 | private String cname; 25 | 26 | private String name; 27 | 28 | private String remark; 29 | 30 | private int status; 31 | 32 | private String host; 33 | 34 | private Integer port; 35 | 36 | private String serverConfig; 37 | 38 | private String clientConfig; 39 | 40 | public Integer getId() { 41 | return id; 42 | } 43 | 44 | public void setId(Integer id) { 45 | this.id = id; 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public void setName(String name) { 53 | this.name = name; 54 | } 55 | 56 | public String getRemark() { 57 | return remark; 58 | } 59 | 60 | public void setRemark(String remark) { 61 | this.remark = remark; 62 | } 63 | 64 | public String getCcode() { 65 | return ccode; 66 | } 67 | 68 | public void setCcode(String ccode) { 69 | this.ccode = ccode; 70 | } 71 | 72 | public String getCname() { 73 | return cname; 74 | } 75 | 76 | public void setCname(String cname) { 77 | this.cname = cname; 78 | } 79 | 80 | public String getHost() { 81 | return host; 82 | } 83 | 84 | public void setHost(String host) { 85 | this.host = host; 86 | } 87 | 88 | public Integer getPort() { 89 | return port; 90 | } 91 | 92 | public void setPort(Integer port) { 93 | this.port = port; 94 | } 95 | 96 | public int getStatus() { 97 | return status; 98 | } 99 | 100 | public void setStatus(int status) { 101 | this.status = status; 102 | } 103 | 104 | public String getServerConfig() { 105 | return serverConfig; 106 | } 107 | 108 | public void setServerConfig(String serverConfig) { 109 | this.serverConfig = serverConfig; 110 | } 111 | 112 | public String getClientConfig() { 113 | return clientConfig; 114 | } 115 | 116 | public void setClientConfig(String clientConfig) { 117 | this.clientConfig = clientConfig; 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/business/model/RouteDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.business.model; 17 | 18 | import java.util.List; 19 | 20 | public class RouteDefinition { 21 | 22 | private Integer id; 23 | 24 | private int status; 25 | 26 | private Integer appId; 27 | 28 | private String name; 29 | 30 | private String remark; 31 | 32 | private FrontendDefinition frontend; 33 | 34 | private BackendDefinition backend; 35 | 36 | private List plugins; 37 | 38 | public Integer getId() { 39 | return id; 40 | } 41 | 42 | public void setId(Integer id) { 43 | this.id = id; 44 | } 45 | 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | public void setName(String name) { 51 | this.name = name; 52 | } 53 | 54 | public String getRemark() { 55 | return remark; 56 | } 57 | 58 | public void setRemark(String remark) { 59 | this.remark = remark; 60 | } 61 | 62 | public Integer getAppId() { 63 | return appId; 64 | } 65 | 66 | public void setAppId(Integer appId) { 67 | this.appId = appId; 68 | } 69 | 70 | public int getStatus() { 71 | return status; 72 | } 73 | 74 | public void setStatus(int status) { 75 | this.status = status; 76 | } 77 | 78 | public FrontendDefinition getFrontend() { 79 | return frontend; 80 | } 81 | 82 | public void setFrontend(FrontendDefinition frontend) { 83 | this.frontend = frontend; 84 | } 85 | 86 | public BackendDefinition getBackend() { 87 | return backend; 88 | } 89 | 90 | public void setBackend(BackendDefinition backend) { 91 | this.backend = backend; 92 | } 93 | 94 | public List getPlugins() { 95 | return plugins; 96 | } 97 | 98 | public void setPlugins(List plugins) { 99 | this.plugins = plugins; 100 | } 101 | 102 | @Override 103 | public String toString() { 104 | return "RouteDefination [id=" + id + ", name=" + name + ", remark=" + remark + ", appId=" + appId + ", status=" 105 | + status + ", frontend=" + frontend + ", backend=" + backend + ", plugins=" + plugins + "]"; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/tree-91585a69.js: -------------------------------------------------------------------------------- 1 | import{d as e,q as s,a_ as l,y as o,r,A as t,z as a,B as n,o as i,i as c,$ as f,a as u,w as h,a9 as d,a$ as p,a1 as m,f as x,J as g,t as v,Q as y,e as b,S as H,E as k,b0 as $,ag as j}from"./index-5b8751dc.js";/* empty css */import"./tsxHelper-11a4c46e.js";const w={class:"flex justify-between items-center h-54px pl-15px pr-15px relative"},_={class:"h-54px flex justify-between items-center absolute top-[50%] right-15px translate-y-[-50%]"},A=e({__name:"Dialog",props:{modelValue:s.bool.def(!1),title:s.string.def("Dialog"),fullscreen:s.bool.def(!0),maxHeight:s.oneOfType([String,Number]).def("400px")},setup(e){const s=e,A=l(),C=o((()=>{const e=["fullscreen","title","maxHeight"],l={...p(),...s};for(const s in l)-1!==e.indexOf(s)&&delete l[s];return l})),E=r(!1),O=()=>{E.value=!u(E)},S=r(t(s.maxHeight)?`${s.maxHeight}px`:s.maxHeight);a((()=>E.value),(async e=>{if(await j(),e){const e=document.documentElement.offsetHeight;S.value=e-55-60-(A.footer?63:0)+"px"}else S.value=t(s.maxHeight)?`${s.maxHeight}px`:s.maxHeight}),{immediate:!0});const D=o((()=>({height:u(S)})));return(s,l)=>{const o=n("Icon");return i(),c(u($),d(C.value,{fullscreen:E.value,"destroy-on-close":"","lock-scroll":"",draggable:"",top:"0","close-on-click-modal":!1,"show-close":!1}),f({header:h((({close:l})=>[x("div",w,[m(s.$slots,"title",{},(()=>[g(v(e.title),1)])),x("div",_,[e.fullscreen?(i(),c(o,{key:0,class:"cursor-pointer is-hover !h-54px mr-10px",icon:E.value?"radix-icons:exit-full-screen":"radix-icons:enter-full-screen",color:"var(--el-color-info)","hover-color":"var(--el-color-primary)",onClick:O},null,8,["icon"])):y("",!0),b(o,{class:"cursor-pointer is-hover !h-54px",icon:"ep:close","hover-color":"var(--el-color-primary)",color:"var(--el-color-info)",onClick:l},null,8,["onClick"])])])])),default:h((()=>[b(u(k),{style:H(D.value)},{default:h((()=>[m(s.$slots,"default")])),_:3},8,["style"])])),_:2},[u(A).footer?{name:"footer",fn:h((()=>[m(s.$slots,"footer")])),key:"0"}:void 0]),1040,["fullscreen"])}}}),C={id:"id",children:"children",pid:"pid"},E=e=>Object.assign({},C,e),O=(e,s={})=>{s=E(s);const{children:l}=s,o=[...e];for(let r=0;r{l=E(l);const o=[],r=[...e],t=new Set,{children:a}=l;for(;r.length;){const e=r[0];if(t.has(e))o.pop(),r.shift();else if(t.add(e),e[a]&&r.unshift(...e[a]),o.push(e),s(e))return o}return null},D=(e,s,l={})=>{const o=(l=E(l)).children;return function e(l){return l.map((e=>({...e}))).filter((l=>(l[o]=l[o]&&e(l[o]),s(l)||l[o]&&l[o].length)))}(e)},q=(e,s)=>e.map((e=>z(e,s))),z=(e,{children:s="children",conversion:l})=>{const o=Array.isArray(e[s])&&e[s].length>0,r=l(e)||{};return o?{...r,[s]:e[s].map((e=>z(e,{children:s,conversion:l})))}:{...r}},B=(e,s,l={})=>{e.forEach((e=>{const o=s(e,l)||e;e.children&&B(e.children,s,o)}))};export{A as _,S as a,O as b,B as e,D as f,q as t}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/api/RouteResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.api; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.web.bind.annotation.DeleteMapping; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PostMapping; 22 | import org.springframework.web.bind.annotation.PutMapping; 23 | import org.springframework.web.bind.annotation.RequestBody; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.RestController; 26 | 27 | import io.agate.admin.business.BusinessException; 28 | import io.agate.admin.business.model.RouteDefinition; 29 | import io.agate.admin.business.param.PageList; 30 | import io.agate.admin.business.param.RouteQuery; 31 | import io.agate.admin.business.service.ManageService; 32 | 33 | @RestController 34 | @RequestMapping("/route") 35 | public class RouteResource { 36 | 37 | @Autowired 38 | private ManageService manageService; 39 | 40 | @GetMapping("/list") 41 | public PageList list(RouteQuery query) { 42 | return manageService.routeList(query); 43 | } 44 | 45 | @GetMapping("/detail") 46 | public RouteDefinition detail(Integer id) { 47 | return manageService.getRouteById(id); 48 | } 49 | 50 | @PostMapping("/save") 51 | public boolean save(@RequestBody RouteDefinition appDefinition) throws BusinessException { 52 | if (appDefinition.getId() == null) { 53 | manageService.createRoute(appDefinition); 54 | } else { 55 | manageService.updateRoute(appDefinition); 56 | } 57 | return true; 58 | } 59 | 60 | @DeleteMapping("/delete") 61 | public boolean delete(@RequestBody Integer[] ids) throws BusinessException { 62 | if (ids != null) { 63 | for (Integer id : ids) { 64 | manageService.deleteRoute(id); 65 | } 66 | } 67 | return true; 68 | } 69 | 70 | @PutMapping("/start") 71 | public boolean start(Integer id) throws BusinessException { 72 | manageService.startRoute(id); 73 | return true; 74 | } 75 | 76 | @PutMapping("/close") 77 | public boolean close(Integer id) throws BusinessException { 78 | manageService.closeRoute(id); 79 | return true; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/context/AgateVerticleFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.context; 17 | 18 | import java.util.concurrent.Callable; 19 | 20 | import io.agate.gateway.verticle.DeployVerticle; 21 | import io.agate.gateway.verticle.GatewayVerticle; 22 | import io.agate.gateway.verticle.LaunchVerticle; 23 | import io.agate.gateway.verticle.ManageVerticle; 24 | import io.agate.gateway.verticle.SystemVerticle; 25 | import io.vertx.core.Promise; 26 | import io.vertx.core.Verticle; 27 | import io.vertx.core.spi.VerticleFactory; 28 | 29 | public class AgateVerticleFactory implements VerticleFactory { 30 | 31 | private static final String AGATE_PREFIX = "agate"; 32 | 33 | private final ApplicationContext context; 34 | 35 | public AgateVerticleFactory(ApplicationContext context) { 36 | this.context = context; 37 | } 38 | 39 | public static String verticleName(Class clazz) { 40 | return AGATE_PREFIX + ":" + clazz.getName(); 41 | } 42 | 43 | @Override 44 | public String prefix() { 45 | return AGATE_PREFIX; 46 | } 47 | 48 | @Override 49 | public void createVerticle(String verticleName, ClassLoader classLoader, Promise> promise) { 50 | promise.complete(() -> createVerticle(verticleName)); 51 | 52 | } 53 | 54 | private Verticle createVerticle(String verticleName) { 55 | String clazz = VerticleFactory.removePrefix(verticleName); 56 | if (SystemVerticle.class.getName().equals(clazz)) { 57 | return new SystemVerticle(context); 58 | } else if (DeployVerticle.class.getName().equals(clazz)) { 59 | return new DeployVerticle(context); 60 | } else if (ManageVerticle.class.getName().equals(clazz)) { 61 | return new ManageVerticle(context); 62 | } else if (GatewayVerticle.class.getName().equals(clazz)) { 63 | return new GatewayVerticle(context); 64 | } else if (LaunchVerticle.class.getName().equals(clazz)) { 65 | return new LaunchVerticle(context); 66 | } 67 | throw new IllegalArgumentException("unsupported verticle type: " + clazz); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /agate-script/agate.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- SQLiteStudio v3.4.4 生成的文件,周四 10月 19 20:36:07 2023 3 | -- 4 | -- 所用的文本编码:UTF-8 5 | -- 6 | PRAGMA foreign_keys = off; 7 | BEGIN TRANSACTION; 8 | 9 | -- 表:DUAL 10 | DROP TABLE IF EXISTS DUAL; 11 | 12 | CREATE TABLE IF NOT EXISTS DUAL ( 13 | id INTEGER PRIMARY KEY AUTOINCREMENT 14 | ); 15 | 16 | 17 | -- 表:t_app 18 | DROP TABLE IF EXISTS t_app; 19 | 20 | CREATE TABLE IF NOT EXISTS t_app ( 21 | id INTEGER PRIMARY KEY AUTOINCREMENT, 22 | gwId INTEGER NOT NULL 23 | REFERENCES t_gateway (id), 24 | name STRING NOT NULL, 25 | json TEXT NOT NULL, 26 | createTime DATETIME NOT NULL, 27 | updateTime DATETIME NOT NULL 28 | ); 29 | 30 | 31 | -- 表:t_cluster 32 | DROP TABLE IF EXISTS t_cluster; 33 | 34 | CREATE TABLE IF NOT EXISTS t_cluster ( 35 | id INTEGER PRIMARY KEY AUTOINCREMENT, 36 | code STRING NOT NULL, 37 | name STRING NOT NULL, 38 | createTime DATETIME NOT NULL, 39 | updateTime DATETIME NOT NULL 40 | ); 41 | 42 | 43 | -- 表:t_gateway 44 | DROP TABLE IF EXISTS t_gateway; 45 | 46 | CREATE TABLE IF NOT EXISTS t_gateway ( 47 | id INTEGER PRIMARY KEY AUTOINCREMENT, 48 | ccode STRING NOT NULL 49 | REFERENCES t_cluster (code), 50 | name STRING NOT NULL, 51 | status INT NOT NULL 52 | DEFAULT (0), 53 | json TEXT NOT NULL, 54 | createTime DATETIME NOT NULL, 55 | updateTime DATETIME NOT NULL 56 | ); 57 | 58 | 59 | -- 表:t_route 60 | DROP TABLE IF EXISTS t_route; 61 | 62 | CREATE TABLE IF NOT EXISTS t_route ( 63 | id INTEGER PRIMARY KEY AUTOINCREMENT, 64 | appId INTEGER NOT NULL 65 | REFERENCES t_app (id), 66 | name STRING NOT NULL, 67 | status INT NOT NULL 68 | DEFAULT (0), 69 | json TEXT NOT NULL, 70 | createTime DATETIME NOT NULL, 71 | updateTime DATETIME NOT NULL 72 | ); 73 | 74 | 75 | -- 表:t_user 76 | DROP TABLE IF EXISTS t_user; 77 | 78 | CREATE TABLE IF NOT EXISTS t_user ( 79 | id INTEGER PRIMARY KEY AUTOINCREMENT, 80 | username STRING NOT NULL 81 | UNIQUE, 82 | password STRING NOT NULL, 83 | enabled BOOLEAN NOT NULL 84 | DEFAULT (1) 85 | ); 86 | 87 | 88 | -- 索引:i_cluster_name 89 | DROP INDEX IF EXISTS i_cluster_name; 90 | 91 | CREATE UNIQUE INDEX IF NOT EXISTS i_cluster_name ON t_gateway ( 92 | ccode, 93 | name 94 | ); 95 | 96 | 97 | -- 索引:i_code_name 98 | DROP INDEX IF EXISTS i_code_name; 99 | 100 | CREATE UNIQUE INDEX IF NOT EXISTS i_code_name ON t_cluster ( 101 | code, 102 | name 103 | ); 104 | 105 | 106 | COMMIT TRANSACTION; 107 | PRAGMA foreign_keys = on; 108 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/handler/internal/ProxyReplyHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.handler.internal; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import io.agate.gateway.context.ContextConstants; 22 | import io.agate.gateway.handler.OrderedHandler; 23 | import io.agate.gateway.options.RouteOptions; 24 | import io.vertx.core.buffer.Buffer; 25 | import io.vertx.core.http.HttpClientResponse; 26 | import io.vertx.core.http.HttpHeaders; 27 | import io.vertx.core.http.HttpServerResponse; 28 | import io.vertx.core.streams.Pipe; 29 | import io.vertx.ext.web.RoutingContext; 30 | 31 | /** 32 | * http route and proxy. 33 | * 34 | * @author dinstone 35 | */ 36 | public class ProxyReplyHandler extends OrderedHandler { 37 | 38 | private static final Logger LOG = LoggerFactory.getLogger(ProxyReplyHandler.class); 39 | 40 | // private BackendOptions backendOptions; 41 | 42 | public ProxyReplyHandler(RouteOptions routeOptions) { 43 | super(600); 44 | // backendOptions = apiOptions.getBackend(); 45 | } 46 | 47 | @Override 48 | public void handle(RoutingContext rc) { 49 | HttpClientResponse beResponse = rc.get(ContextConstants.BACKEND_RESPONSE); 50 | HttpServerResponse feResponse = rc.response(); 51 | feResponse.setStatusCode(beResponse.statusCode()); 52 | feResponse.headers().addAll(beResponse.headers()); 53 | 54 | long len = getContentLength(beResponse); 55 | if (len == 0) { 56 | feResponse.end(); 57 | return; 58 | } 59 | 60 | // beResponse.exceptionHandler(t -> { 61 | // if (LOG.isDebugEnabled()) { 62 | // LOG.debug("pipe from backend to front error", t); 63 | // } 64 | // beRequest.reset(); 65 | // }); 66 | 67 | Pipe pipe = beResponse.pipe(); 68 | pipe.endOnFailure(false).endOnSuccess(true); 69 | pipe.to(feResponse).onFailure(t -> { 70 | pipe.close(); 71 | }); 72 | 73 | } 74 | 75 | private long getContentLength(HttpClientResponse response) { 76 | String tc = response.getHeader(HttpHeaders.TRANSFER_ENCODING); 77 | if ("chunked".equalsIgnoreCase(tc)) { 78 | return -1; 79 | } 80 | 81 | try { 82 | return Long.parseLong(response.getHeader(HttpHeaders.CONTENT_LENGTH)); 83 | } catch (Exception e) { 84 | // ignore 85 | } 86 | return -1; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/api/GatewayResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.api; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.web.bind.annotation.DeleteMapping; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PostMapping; 22 | import org.springframework.web.bind.annotation.PutMapping; 23 | import org.springframework.web.bind.annotation.RequestBody; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.RestController; 26 | 27 | import io.agate.admin.business.BusinessException; 28 | import io.agate.admin.business.model.GatewayDefinition; 29 | import io.agate.admin.business.param.GatewayQuery; 30 | import io.agate.admin.business.param.PageList; 31 | import io.agate.admin.business.service.ManageService; 32 | 33 | @RestController 34 | @RequestMapping("/gateway") 35 | public class GatewayResource { 36 | 37 | @Autowired 38 | private ManageService manageService; 39 | 40 | @GetMapping("/list") 41 | public PageList list(GatewayQuery query) { 42 | return manageService.gatewayList(query); 43 | } 44 | 45 | @GetMapping("/detail") 46 | public GatewayDefinition detail(Integer id) { 47 | return manageService.getGatewayById(id); 48 | } 49 | 50 | @PostMapping("/save") 51 | public boolean save(@RequestBody GatewayDefinition gatewayDefinition) throws BusinessException { 52 | if (gatewayDefinition.getId() == null) { 53 | manageService.createGateway(gatewayDefinition); 54 | } else { 55 | manageService.updateGateway(gatewayDefinition); 56 | } 57 | return true; 58 | } 59 | 60 | @DeleteMapping("/delete") 61 | public boolean delete(@RequestBody Integer[] ids) throws BusinessException { 62 | if (ids != null) { 63 | for (Integer id : ids) { 64 | manageService.deleteGateway(id); 65 | } 66 | } 67 | return true; 68 | } 69 | 70 | @PutMapping("/start") 71 | public boolean start(Integer id) throws BusinessException { 72 | manageService.startGateway(id); 73 | return true; 74 | } 75 | 76 | @PutMapping("/close") 77 | public boolean close(Integer id) throws BusinessException { 78 | manageService.closeGateway(id); 79 | return true; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/http/RestfulUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.http; 17 | 18 | import io.vertx.core.json.JsonObject; 19 | import io.vertx.ext.web.RoutingContext; 20 | 21 | public class RestfulUtil { 22 | 23 | private static final String CONTENT_TYPE_NAME = "Content-Type"; 24 | private static final String CONTENT_TYPE_JSON = "application/json"; 25 | 26 | public static void success(RoutingContext ctx) { 27 | success(ctx, null); 28 | } 29 | 30 | public static void success(RoutingContext ctx, Object result) { 31 | JsonObject json = new JsonObject().put("status", "1").put("result", result); 32 | ctx.response().putHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_JSON).end(json.encode()); 33 | } 34 | 35 | public static void failure(RoutingContext ctx, String message) { 36 | JsonObject json = new JsonObject().put("status", "-1").put("message", message); 37 | ctx.response().putHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_JSON).end(json.encode()); 38 | } 39 | 40 | public static void failure(RoutingContext ctx, Throwable throwable) { 41 | JsonObject json = new JsonObject().put("status", "-1").put("message", getMessage(throwable)); 42 | ctx.response().putHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_JSON).end(json.encode()); 43 | } 44 | 45 | public static void exception(RoutingContext rc, int statusCode, String message) { 46 | JsonObject json = new JsonObject().put("status", statusCode).put("message", message); 47 | rc.response().setStatusCode(statusCode).putHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_JSON).end(json.encode()); 48 | } 49 | 50 | public static void exception(RoutingContext rc, int statusCode, Throwable failure) { 51 | JsonObject json = new JsonObject().put("status", statusCode).put("message", getMessage(failure)); 52 | rc.response().setStatusCode(statusCode).putHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_JSON).end(json.encode()); 53 | } 54 | 55 | private static String getMessage(Throwable t) { 56 | if (t == null) { 57 | return ""; 58 | } 59 | String message = t.getMessage(); 60 | if (message == null) { 61 | return getMessage(t.getCause()); 62 | } 63 | return message; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/plugin/PluginOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.plugin; 17 | 18 | import java.util.Objects; 19 | 20 | import io.vertx.core.json.JsonObject; 21 | 22 | public class PluginOptions { 23 | 24 | private String plugin; 25 | 26 | private JsonObject options; 27 | 28 | public PluginOptions(String plugin, JsonObject options) { 29 | this.plugin = plugin; 30 | this.options = options; 31 | } 32 | 33 | public PluginOptions(JsonObject value) { 34 | fromJson(value); 35 | } 36 | 37 | public String getPlugin() { 38 | return plugin; 39 | } 40 | 41 | public void setPlugin(String plugin) { 42 | this.plugin = plugin; 43 | } 44 | 45 | public JsonObject getOptions() { 46 | if (options == null) { 47 | options = new JsonObject(); 48 | } 49 | return options; 50 | } 51 | 52 | public void setOptions(JsonObject options) { 53 | this.options = options; 54 | } 55 | 56 | public void fromJson(JsonObject json) { 57 | for (java.util.Map.Entry member : json) { 58 | Object value = member.getValue(); 59 | switch (member.getKey()) { 60 | case "plugin": 61 | if (value instanceof String) { 62 | this.setPlugin((String) value); 63 | } 64 | break; 65 | case "options": 66 | if (value instanceof JsonObject) { 67 | this.setOptions((JsonObject) value); 68 | } 69 | break; 70 | } 71 | } 72 | } 73 | 74 | public JsonObject toJson() { 75 | JsonObject json = new JsonObject(); 76 | 77 | if (plugin != null) { 78 | json.put("plugin", plugin); 79 | } 80 | if (options != null) { 81 | json.put("options", options); 82 | } 83 | 84 | return json; 85 | } 86 | 87 | @Override 88 | public int hashCode() { 89 | return Objects.hash(plugin); 90 | } 91 | 92 | @Override 93 | public boolean equals(Object obj) { 94 | if (this == obj) 95 | return true; 96 | if (obj == null) 97 | return false; 98 | if (getClass() != obj.getClass()) 99 | return false; 100 | PluginOptions other = (PluginOptions) obj; 101 | return Objects.equals(plugin, other.plugin); 102 | } 103 | 104 | @Override 105 | public String toString() { 106 | return "PluginOptions [plugin=" + plugin + ", options=" + options + "]"; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /agate-gateway/src/main/java/io/agate/gateway/utils/ConfigUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.gateway.utils; 17 | 18 | import io.vertx.core.json.JsonObject; 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | import java.io.FileInputStream; 23 | import java.io.FileNotFoundException; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.util.Scanner; 27 | 28 | public class ConfigUtil { 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(ConfigUtil.class); 31 | 32 | /** 33 | * load config resource from file path or class path. 34 | * 35 | * @param resourceLocation 36 | * @return 37 | */ 38 | public static JsonObject loadConfig(String resourceLocation) { 39 | InputStream resourceStream = null; 40 | try { 41 | resourceStream = new FileInputStream(resourceLocation); 42 | } catch (FileNotFoundException e) { 43 | LOG.warn("file not found from file path: {}", resourceLocation); 44 | } 45 | 46 | if (resourceStream == null) { 47 | resourceStream = getResourceStream(resourceLocation); 48 | } 49 | 50 | if (resourceStream == null) { 51 | LOG.warn("file not found from class path:{}", resourceLocation); 52 | throw new RuntimeException("failed to load config : " + resourceLocation); 53 | } 54 | 55 | try (Scanner scanner = new Scanner(resourceStream, "UTF-8").useDelimiter("\\A")) { 56 | return new JsonObject(scanner.next()); 57 | } catch (Exception e) { 58 | LOG.error("failed to load config : " + resourceLocation, e); 59 | throw new RuntimeException("failed to load config : " + resourceLocation, e); 60 | } finally { 61 | try { 62 | resourceStream.close(); 63 | } catch (IOException ignored) { 64 | } 65 | } 66 | } 67 | 68 | private static InputStream getResourceStream(String resource) { 69 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 70 | if (classLoader == null) { 71 | classLoader = ConfigUtil.class.getClassLoader(); 72 | } 73 | return classLoader.getResourceAsStream(resource); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /agate-admin/src/main/java/io/agate/admin/store/ConsulCatalogRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020~2024 dinstone 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.agate.admin.store; 17 | 18 | import com.ecwid.consul.v1.ConsulClient; 19 | import com.ecwid.consul.v1.Response; 20 | import com.ecwid.consul.v1.catalog.CatalogServiceRequest; 21 | import com.ecwid.consul.v1.catalog.model.CatalogService; 22 | import com.ecwid.consul.v1.kv.model.GetValue; 23 | import io.agate.admin.business.port.CatalogRepository; 24 | 25 | import java.util.*; 26 | import java.util.stream.Collectors; 27 | 28 | public class ConsulCatalogRepository implements CatalogRepository { 29 | 30 | private final ConsulClient consulClient; 31 | 32 | public ConsulCatalogRepository(ConsulClient consulClient) { 33 | this.consulClient = consulClient; 34 | } 35 | 36 | @Override 37 | public List> getMetas(String service) { 38 | CatalogServiceRequest request = CatalogServiceRequest.newBuilder().build(); 39 | Response> consulResponse = consulClient.getCatalogService(service, request); 40 | 41 | List> instances = new LinkedList<>(); 42 | for (CatalogService cs : consulResponse.getValue()) { 43 | Map instance = cs.getServiceMeta(); 44 | if (instance != null) { 45 | instances.add(instance); 46 | } 47 | } 48 | return instances; 49 | } 50 | 51 | @Override 52 | public void deleteKey(String key) { 53 | consulClient.deleteKVValue(key); 54 | } 55 | 56 | @Override 57 | public List getKeys(String key) { 58 | Response> rv = consulClient.getKVValues(key); 59 | if (rv.getValue() == null) { 60 | return Collections.emptyList(); 61 | } 62 | return rv.getValue().stream().map(GetValue::getKey).collect(Collectors.toList()); 63 | } 64 | 65 | @Override 66 | public Optional getValue(String k) { 67 | Response rv = consulClient.getKVValue(k); 68 | GetValue value = rv.getValue(); 69 | if (value == null) { 70 | return Optional.empty(); 71 | } 72 | return Optional.of(value.getValue()); 73 | } 74 | 75 | @Override 76 | public void putValue(String key, String value) { 77 | consulClient.setKVValue(key, value); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/Login-3cc6bcdf.js: -------------------------------------------------------------------------------- 1 | import{d as t,b as e,r as s,o as a,c as l,e as i,w as x,f as p,n as r,a as o,t as n,g as m,T as c,h as d,i as u,E as _,j as g,k as v,p as f,l as h,_ as w}from"./index-5b8751dc.js";import{T as j,_ as b,a as y}from"./LocaleDropdown.vue_vue_type_script_setup_true_lang-f77fc5b1.js";import{_ as k}from"./LoginForm.vue_vue_type_script_setup_true_lang-d1c06f36.js";import{_ as T}from"./RegisterForm.vue_vue_type_script_setup_true_lang-73f185cd.js";import"./tsxHelper-11a4c46e.js";import"./useForm-95be4c91.js";/* empty css *//* empty css *//* empty css */import"./useIcon-f4304df6.js";/* empty css *//* empty css */import"./index-219675da.js";import"./index-e446de42.js";import"./useValidator-0a43379b.js";const I=t=>(f("data-v-78683172"),t=t(),h(),t),L={class:"relative flex mx-auto min-h-100vh"},F={class:"flex items-center relative text-white"},R=I((()=>p("img",{src:y,alt:"",class:"w-48px h-48px mr-10px"},null,-1))),C={class:"text-20px font-bold"},D={class:"flex justify-center items-center h-[calc(100%-60px)]"},E={class:"text-3xl text-white text-center",key:"2"},H={class:"mt-5 font-normal text-white text-14px text-center",key:"3"},z=I((()=>p("img",{src:"/assets/login-box-bg-fec91044.svg",key:"1",alt:"",class:"w-350px"},null,-1))),A={class:"flex-1 p-30px lt-sm:p-10px dark:bg-[var(--login-bg-color)] relative"},B={class:"flex justify-between items-center text-white at-2xl:justify-end at-xl:justify-end"},G={class:"flex items-center at-2xl:hidden at-xl:hidden"},P=I((()=>p("img",{src:y,alt:"",class:"w-48px h-48px mr-10px"},null,-1))),V={class:"text-20px font-bold"},$={class:"flex justify-end items-center space-x-10px"},q={class:"h-full flex items-center m-auto w-[100%] at-2xl:max-w-500px at-xl:max-w-500px at-md:max-w-500px at-lg:max-w-500px"},J=w(t({__name:"Login",setup(t){const{getPrefixCls:f}=g(),h=f("login"),w=e(),{t:y}=v(),I=s(!0),J=()=>{I.value=!1},K=()=>{I.value=!0};return(t,e)=>(a(),l("div",{class:r([o(h),"h-[100%] relative lt-xl:bg-[var(--login-bg-color)] lt-sm:px-10px lt-xl:px-10px lt-md:px-10px"])},[i(o(_),{class:"h-full"},{default:x((()=>[p("div",L,[p("div",{class:r(`${o(h)}__left flex-1 bg-gray-500 bg-opacity-20 relative p-30px lt-xl:hidden`)},[p("div",F,[R,p("span",C,n(o(m)(o(w).getTitle)),1)]),p("div",D,[i(c,{appear:"",tag:"div","enter-active-class":"animate__animated animate__bounceInLeft"},{default:x((()=>[p("div",E,n(o(y)("login.welcome")),1),p("div",H,n(o(y)("login.message")),1),z])),_:1})])],2),p("div",A,[p("div",B,[p("div",G,[P,p("span",V,n(o(m)(o(w).getTitle)),1)]),p("div",$,[i(o(j)),i(o(b),{class:"lt-xl:text-white dark:text-white"})])]),i(d,{appear:"","enter-active-class":"animate__animated animate__bounceInRight"},{default:x((()=>[p("div",q,[I.value?(a(),u(o(k),{key:0,class:"p-20px h-auto m-auto lt-xl:rounded-3xl lt-xl:light:bg-white",onToRegister:J})):(a(),u(o(T),{key:1,class:"p-20px h-auto m-auto lt-xl:rounded-3xl lt-xl:light:bg-white",onToLogin:K}))])])),_:1})])])])),_:1})],2))}}),[["__scopeId","data-v-78683172"]]);export{J as default}; 2 | -------------------------------------------------------------------------------- /agate-admin/src/main/resources/static/assets/el-link-0543119b.css: -------------------------------------------------------------------------------- 1 | .el-link{--el-link-font-size:var(--el-font-size-base);--el-link-font-weight:var(--el-font-weight-primary);--el-link-text-color:var(--el-text-color-regular);--el-link-hover-text-color:var(--el-color-primary);--el-link-disabled-text-color:var(--el-text-color-placeholder);align-items:center;color:var(--el-link-text-color);cursor:pointer;display:inline-flex;flex-direction:row;font-size:var(--el-link-font-size);font-weight:var(--el-link-font-weight);justify-content:center;outline:none;padding:0;position:relative;text-decoration:none;vertical-align:middle}.el-link:hover{color:var(--el-link-hover-text-color)}.el-link.is-underline:hover:after{border-bottom:1px solid var(--el-link-hover-text-color);bottom:0;content:"";height:0;left:0;position:absolute;right:0}.el-link.is-disabled{color:var(--el-link-disabled-text-color);cursor:not-allowed}.el-link [class*=el-icon-]+span{margin-left:5px}.el-link.el-link--default:after{border-color:var(--el-link-hover-text-color)}.el-link__inner{align-items:center;display:inline-flex;justify-content:center}.el-link.el-link--primary{--el-link-text-color:var(--el-color-primary);--el-link-hover-text-color:var(--el-color-primary-light-3);--el-link-disabled-text-color:var(--el-color-primary-light-5)}.el-link.el-link--primary:after{border-color:var(--el-link-text-color)}.el-link.el-link--primary.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--success{--el-link-text-color:var(--el-color-success);--el-link-hover-text-color:var(--el-color-success-light-3);--el-link-disabled-text-color:var(--el-color-success-light-5)}.el-link.el-link--success:after{border-color:var(--el-link-text-color)}.el-link.el-link--success.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--warning{--el-link-text-color:var(--el-color-warning);--el-link-hover-text-color:var(--el-color-warning-light-3);--el-link-disabled-text-color:var(--el-color-warning-light-5)}.el-link.el-link--warning:after{border-color:var(--el-link-text-color)}.el-link.el-link--warning.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--danger{--el-link-text-color:var(--el-color-danger);--el-link-hover-text-color:var(--el-color-danger-light-3);--el-link-disabled-text-color:var(--el-color-danger-light-5)}.el-link.el-link--danger:after{border-color:var(--el-link-text-color)}.el-link.el-link--danger.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--error{--el-link-text-color:var(--el-color-error);--el-link-hover-text-color:var(--el-color-error-light-3);--el-link-disabled-text-color:var(--el-color-error-light-5)}.el-link.el-link--error:after{border-color:var(--el-link-text-color)}.el-link.el-link--error.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--info{--el-link-text-color:var(--el-color-info);--el-link-hover-text-color:var(--el-color-info-light-3);--el-link-disabled-text-color:var(--el-color-info-light-5)}.el-link.el-link--info:after{border-color:var(--el-link-text-color)}.el-link.el-link--info.is-underline:hover:after{border-color:var(--el-link-text-color)} 2 | --------------------------------------------------------------------------------