diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..95e50e3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +apigw/target/** +apigw/.gitignore + +### IntelliJ IDEA ### +apigw/.idea +apigw/*.iws +apigw/*.iml +apigw/*.ipr + +### NetBeans ### +apigw/nbproject/ +apigw/nbbuild/ +apigw/dist/ +apigw/nbdist/ +apigw/.nb-gradle/ +apigw/build/ + +### VS Code ### +.vscode/ diff --git a/Dockerfile b/Dockerfile index cb15a4d..3f7cb82 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ibmjava:sfj +FROM amazoncorretto:17-alpine3.16 as builder LABEL author="Piotr Biernat" LABEL service="api-gw" @@ -8,8 +8,22 @@ LABEL version="1.0" RUN mkdir /app WORKDIR /app -COPY ./apigw/target/api-gw-0.0.1-SNAPSHOT.jar /app/api-gw.jar +COPY apigw . +RUN ./mvnw clean compile install -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/api-gw.jar", "--spring.profiles.active=docker"] +FROM amazoncorretto:17-alpine3.16 -EXPOSE 80 +#ENV CA_CERT_DIR /usr/lib/jvm/java-8-amazon-corretto/lib/security + +COPY --from=builder /app/target/apigw-dev-jar-with-dependencies.jar /api-gw.jar + +# Add own ca to cacert trusted db +#COPY --from=builder /app/src/main/resources/ca.pem /tmp/ca.pem +#RUN keytool -import -trustcacerts -keystore ${CA_CERT_DIR}/cacerts \ +# -storepass changeit -noprompt -alias mycert -file /tmp/ca.pem && \ +# rm /tmp/ca.pem + +# "-Djavax.net.debug=all", +ENTRYPOINT ["java", "-Xmx1g", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/api-gw.jar", "--spring.profiles.active=docker"] + +EXPOSE 443 diff --git a/api-gateway/.gitignore b/api-gateway/.gitignore new file mode 100644 index 0000000..75f8332 --- /dev/null +++ b/api-gateway/.gitignore @@ -0,0 +1,19 @@ +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# VS Code +.vscode/ + +# Maven +target/ +bin/ +pom.xml.* +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +# .mvn/wrapper/maven-wrapper.jar diff --git a/api-gateway/.mvn/wrapper/maven-wrapper.jar b/api-gateway/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..bf82ff0 Binary files /dev/null and b/api-gateway/.mvn/wrapper/maven-wrapper.jar differ diff --git a/api-gateway/.mvn/wrapper/maven-wrapper.properties b/api-gateway/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..84b111f --- /dev/null +++ b/api-gateway/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/apigw/mvnw b/api-gateway/mvnw similarity index 79% rename from apigw/mvnw rename to api-gateway/mvnw index 8a8fb22..b7f0646 100755 --- a/apigw/mvnw +++ b/api-gateway/mvnw @@ -8,7 +8,7 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven Start Up Batch script +# Apache Maven Wrapper startup batch script, version 3.1.1 # # Required ENV vars: # ------------------ @@ -27,7 +27,6 @@ # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir # MAVEN_OPTS - parameters passed to the Java VM when running Maven # e.g. to debug Maven itself, use # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @@ -62,9 +61,9 @@ case "`uname`" in # See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" + JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME else - export JAVA_HOME="/Library/Java/Home" + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME fi fi ;; @@ -76,36 +75,8 @@ if [ -z "$JAVA_HOME" ] ; then fi fi -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` [ -n "$CLASSPATH" ] && @@ -114,8 +85,6 @@ fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" [ -n "$JAVA_HOME" ] && JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" fi @@ -163,12 +132,9 @@ if [ -z "$JAVA_HOME" ] ; then echo "Warning: JAVA_HOME environment variable is not set." fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { - if [ -z "$1" ] then echo "Path not specified to find_maven_basedir" @@ -188,7 +154,7 @@ find_maven_basedir() { fi # end of workaround done - echo "${basedir}" + printf '%s' "$(cd "$basedir"; pwd)" } # concatenates all lines of a file @@ -198,11 +164,16 @@ concat_lines() { fi } -BASE_DIR=`find_maven_basedir "$(pwd)"` +BASE_DIR=$(find_maven_basedir "$(dirname $0)") if [ -z "$BASE_DIR" ]; then exit 1; fi +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi + ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. @@ -216,16 +187,16 @@ else echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." fi if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" fi while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;; esac done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" + echo "Downloading from: $wrapperUrl" fi wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" if $cygwin; then @@ -233,42 +204,49 @@ else fi if command -v wget > /dev/null; then + QUIET="--quiet" if [ "$MVNW_VERBOSE" = true ]; then echo "Found wget ... using wget" + QUIET="" fi if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" fi + [ $? -eq 0 ] || rm -f "$wrapperJarPath" elif command -v curl > /dev/null; then + QUIET="--silent" if [ "$MVNW_VERBOSE" = true ]; then echo "Found curl ... using curl" + QUIET="" fi if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L fi - + [ $? -eq 0 ] || rm -f "$wrapperJarPath" else if [ "$MVNW_VERBOSE" = true ]; then echo "Falling back to using Java to download" fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" # For Cygwin, switch paths to Windows format before running javac if $cygwin; then + javaSource=`cygpath --path --windows "$javaSource"` javaClass=`cygpath --path --windows "$javaClass"` fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then if [ "$MVNW_VERBOSE" = true ]; then echo " - Compiling MavenWrapperDownloader.java ..." fi # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") + ("$JAVA_HOME/bin/javac" "$javaSource") fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ -e "$javaClass" ]; then # Running the downloader if [ "$MVNW_VERBOSE" = true ]; then echo " - Running MavenWrapperDownloader.java ..." @@ -282,16 +260,10 @@ fi # End of extension ########################################################################################## -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` [ -n "$CLASSPATH" ] && @@ -311,6 +283,5 @@ exec "$JAVACMD" \ $MAVEN_OPTS \ $MAVEN_DEBUG_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/apigw/mvnw.cmd b/api-gateway/mvnw.cmd similarity index 89% rename from apigw/mvnw.cmd rename to api-gateway/mvnw.cmd index 1d8ab01..cba1f04 100644 --- a/apigw/mvnw.cmd +++ b/api-gateway/mvnw.cmd @@ -1,188 +1,187 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.1.1 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml new file mode 100644 index 0000000..280f894 --- /dev/null +++ b/api-gateway/pom.xml @@ -0,0 +1,410 @@ + + + 4.0.0 + com.egommerce + api-gateway + api-gateway + API Gateway - built using netflix-zuul v2 + dev + https://egommerce.dev + jar + + + 18 + 1.8 + 1.8 + true + UTF-8 + + 2.3.0 + 1.10.17 + 2.4.4 + 3.0.13 + 2.5.14-01 + + 2.9.1-01 + + 1.7.36 + 4.1.84.Final + 0.0.15.Final + + + + + + + groovy-plugins-release + https://groovy.jfrog.io/artifactory/plugins-release + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + org.codehaus.groovy + groovy-eclipse-batch + ${groovy.eclipse.batch} + compile + + + org.codehaus.groovy + groovy-eclipse-compiler + ${groovy.eclipse.compiler} + compile + + + + groovy-eclipse-compiler + UTF-8 + true + true + true + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + + + + true + com.egommerce.apigateway.Bootstrap + + + + jar-with-dependencies + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M2 + + + enforce + + + + + + + enforce + + + + + + + + src/main/resources + true + + ssl/ + + + + src/main/resources + false + + ssl/ + + + + + + + + com.netflix.zuul + zuul-core + ${netflix.zull.version} + + + com.netflix.zuul + zuul-groovy + ${netflix.zull.version} + + + org.codehaus.groovy + groovy-all + + + + + com.netflix.eureka + eureka-client + ${netflix.eureka.version} + + + + com.netflix.zuul + zuul-guice + ${netflix.zull.version} + + + com.google.guava + guava + 31.1-jre + + + org.codehaus.groovy + groovy-all + + ${groovy.all} + pom + + + org.awaitility + awaitility + 4.2.0 + + + io.netty + netty-buffer + ${io.netty.version} + + + + org.bouncycastle + bcprov-jdk15on + 1.68 + + + org.bouncycastle + bcpkix-jdk15on + 1.68 + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-simple + ${slf4j.version} + + + + + + + com.netflix.eureka + eureka-client + ${netflix.eureka.version} + + + com.netflix.archaius + archaius-core + 0.7.7 + + + com.netflix.netflix-commons + netflix-commons-util + 0.3.0 + + + com.netflix.ribbon + ribbon-core + 2.4.8 + + + com.netflix.ribbon + ribbon-archaius + 2.4.8 + + + com.netflix.ribbon + ribbon-eureka + 2.4.8 + + + com.netflix.ribbon + ribbon-loadbalancer + 2.4.8 + + + com.netflix.servo + servo-core + 0.10.1 + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + com.google.guava + guava + 31.1-jre + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-simple + ${slf4j.version} + + + commons-configuration + commons-configuration + 1.10 + + + org.hamcrest + hamcrest-core + 1.3 + + + com.google.errorprone + error_prone_annotations + 2.11.0 + + + commons-io + commons-io + 2.11 + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + commons-logging + commons-logging + 1.1.3 + + + com.google.inject + guice + 5.1.0 + + + com.fasterxml.jackson.core + jackson-core + 2.13.4 + + + com.fasterxml.jackson.core + jackson-databind + 2.13.4.2 + + + com.fasterxml.jackson.core + jackson-annotations + 2.13.4 + + + io.reactivex + rxjava + 1.3.8 + + + com.google.code.findbugs + jsr305 + 3.0.1 + + + + io.netty.incubator + netty-incubator-transport-native-io_uring + ${io.netty.io_uring.version} + + + io.netty + netty-bom + ${io.netty.version} + + + io.netty + netty-buffer + ${io.netty.version} + + + io.netty + netty-codec-http + ${io.netty.version} + + + io.netty + netty-codec-http2 + ${io.netty.version} + + + io.netty + netty-tcnative-boringssl-static + 2.0.54.Final + + + io.netty + netty-common + ${io.netty.version} + + + io.netty + netty-handler + ${io.netty.version} + + + io.netty + netty-transport + ${io.netty.version} + + + io.netty + netty-codec-haproxy + ${io.netty.version} + + + io.netty + netty-transport-native-unix-common + ${io.netty.version} + + + io.netty + netty-transport-native-epoll + ${io.netty.version} + linux-x86_64 + + + + \ No newline at end of file diff --git a/api-gateway/run.sh b/api-gateway/run.sh new file mode 100644 index 0000000..02841a0 --- /dev/null +++ b/api-gateway/run.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# --add-opens java.base/jdk.internal.misc=ALL-UNNAMED \ +java -jar target/api-gateway-dev-jar-with-dependencies.jar \ + -Xmx1g \ + -Djava.security.egd=file:/dev/./urandom \ + -Djavax.net.debug=ALL \ + -DTZ=GMT \ + -Darchaius.deployment.environment=test \ + -Dcom.sun.management.jmxremote \ + -Dcom.sun.management.jmxremote.local.only=false \ + -Deureka.validateInstanceId=false \ + -Deureka.mt.num_retries=1 \ + -X -e diff --git a/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/endpoint/Healthcheck.groovy b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/endpoint/Healthcheck.groovy new file mode 100644 index 0000000..e5c6040 --- /dev/null +++ b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/endpoint/Healthcheck.groovy @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.egommerce.apigateway.filters.endpoint + +import com.netflix.zuul.filters.http.HttpSyncEndpoint +import com.netflix.zuul.message.http.HttpRequestMessage +import com.netflix.zuul.message.http.HttpResponseMessage +import com.netflix.zuul.message.http.HttpResponseMessageImpl +import com.netflix.zuul.stats.status.StatusCategoryUtils +import com.netflix.zuul.stats.status.ZuulStatusCategory + +/** + * Healthcheck Sample Endpoint + * + * Author: Arthur Gonigberg + * Date: November 21, 2017 + */ +class Healthcheck extends HttpSyncEndpoint { + + @Override + HttpResponseMessage apply(HttpRequestMessage request) { + HttpResponseMessage resp = new HttpResponseMessageImpl(request.getContext(), request, 200) + resp.setBodyAsText("healthy") + + // print "HEALTHCHECK::PLUGIN" + + // need to set this manually since we are not going through the ProxyEndpoint + StatusCategoryUtils.setStatusCategory(request.getContext(), ZuulStatusCategory.SUCCESS) + + return resp + } +} diff --git a/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/inbound/DebugRequest.groovy b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/inbound/DebugRequest.groovy new file mode 100644 index 0000000..83ac47a --- /dev/null +++ b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/inbound/DebugRequest.groovy @@ -0,0 +1,70 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.egommerce.apigateway.filters.inbound + +import com.netflix.zuul.context.Debug +import com.netflix.zuul.context.SessionContext +import com.netflix.zuul.filters.http.HttpInboundSyncFilter +import com.netflix.zuul.message.http.HttpRequestMessage + +/** + * Add debug request info to the context if request is marked as debug. + * + * Author: Arthur Gonigberg + * Date: December 22, 2017 + */ +class DebugRequest extends HttpInboundSyncFilter { + + @Override + int filterOrder() { + return 21 + } + + @Override + boolean shouldFilter(HttpRequestMessage request) { + return true + // return request.getContext().debugRequest() + } + + @Override + boolean needsBodyBuffered(HttpRequestMessage request) { + return shouldFilter(request) + } + + @Override + HttpRequestMessage apply(HttpRequestMessage request) { + SessionContext ctx = request.getContext() + + Debug.addRequestDebug(ctx, "REQUEST:: " + request.getOriginalScheme() + " " + request.getOriginalHost() + ":" + request.getOriginalPort()) + + Debug.addRequestDebug(ctx, "REQUEST:: > " + request.getMethod() + " " + request.reconstructURI() + " " + request.getProtocol()) + + Iterator headerIt = request.getHeaders().iterator() + while (headerIt.hasNext()) { + String name = (String) headerIt.next() + String value = request.getHeaders().getFirst(name) + Debug.addRequestDebug(ctx, "REQUEST:: > " + name + ":" + value) + + } + + if (request.hasBody()) { + Debug.addRequestDebug(ctx, "REQUEST:: > " + request.getBodyAsText()) + } + + return request + } +} diff --git a/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/inbound/Routes.groovy b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/inbound/Routes.groovy new file mode 100644 index 0000000..99f1186 --- /dev/null +++ b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/inbound/Routes.groovy @@ -0,0 +1,69 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.egommerce.apigateway.filters.inbound + +import com.netflix.zuul.context.SessionContext +import com.netflix.zuul.filters.endpoint.ProxyEndpoint +import com.netflix.zuul.filters.http.HttpInboundSyncFilter +import com.netflix.zuul.message.http.HttpRequestMessage +import com.egommerce.apigateway.filters.endpoint.Healthcheck + +/** + * Routes configuration + * + * Author: Arthur Gonigberg + * Date: November 21, 2017 + */ +class Routes extends HttpInboundSyncFilter { + + @Override + int filterOrder() { + return 0 + } + + @Override + boolean shouldFilter(HttpRequestMessage httpRequestMessage) { + return true + } + + @Override + HttpRequestMessage apply(HttpRequestMessage request) { + SessionContext context = request.getContext() + String path = request.getPath() + + // print "ROUTES::PLUGIN" + + // Route healthchecks to the healthcheck endpoint.; + if (path.equalsIgnoreCase("/healthcheck")) { + context.setEndpoint(Healthcheck.class.getCanonicalName()) + } + else if (path.containsIgnoreCase("/auth")) { + context.setEndpoint(ProxyEndpoint.class.getCanonicalName()) + context.setRouteVIP("identity-svc") + } + else if (path.containsIgnoreCase("/basket")) { + context.setEndpoint(ProxyEndpoint.class.getCanonicalName()) + context.setRouteVIP("basket-svc") + } + else { + context.setEndpoint(ProxyEndpoint.class.getCanonicalName()) + context.setRouteVIP("unknown-svc") + } + + return request + } +} diff --git a/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/outbound/ZuulResponseFilter.groovy b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/outbound/ZuulResponseFilter.groovy new file mode 100644 index 0000000..5ac8c97 --- /dev/null +++ b/api-gateway/src/main/groovy/com/egommerce/apigateway/filters/outbound/ZuulResponseFilter.groovy @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.egommerce.apigateway.filters.outbound + +import com.netflix.config.DynamicBooleanProperty +import com.netflix.config.DynamicStringProperty +import com.netflix.zuul.context.Debug +import com.netflix.zuul.context.SessionContext +import com.netflix.zuul.exception.ZuulException +import com.netflix.zuul.filters.http.HttpOutboundSyncFilter +import com.netflix.zuul.message.Headers +import com.netflix.zuul.message.http.HttpResponseMessage +import com.netflix.zuul.niws.RequestAttempts +import com.netflix.zuul.passport.CurrentPassport +import com.netflix.zuul.stats.status.StatusCategory +import com.netflix.zuul.stats.status.StatusCategoryUtils +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +import static com.netflix.zuul.constants.ZuulHeaders.* + +/** + * Sample Response Filter - adding custom response headers for better analysis of how the request was proxied + * + * Author: Arthur Gonigberg + * Date: December 21, 2017 + */ +class ZuulResponseFilter extends HttpOutboundSyncFilter { + private static final Logger logger = LoggerFactory.getLogger(ZuulResponseFilter.class) + + private static final DynamicBooleanProperty SEND_RESPONSE_HEADERS = + new DynamicBooleanProperty("zuul.responseFilter.send.headers", true) + + private static final DynamicStringProperty INSTANCE_ID = + new DynamicStringProperty("eureka.instanceId", "127.0.0.1") // FIXME + + @Override + int filterOrder() { + return 999 + } + + @Override + boolean shouldFilter(HttpResponseMessage request) { + return true + } + + @Override + HttpResponseMessage apply(HttpResponseMessage response) { + SessionContext context = response.getContext() + + if (SEND_RESPONSE_HEADERS.get()) { + Headers headers = response.getHeaders() + + StatusCategory statusCategory = StatusCategoryUtils.getStatusCategory(response) + if (statusCategory != null) { + headers.set(X_ZUUL_STATUS, statusCategory.name()) + } + + RequestAttempts attempts = RequestAttempts.getFromSessionContext(response.getContext()) + String headerStr = "" + if (attempts != null) { + headerStr = attempts.toString() + } + headers.set(X_ZUUL_PROXY_ATTEMPTS, headerStr) + + headers.set(X_ZUUL, "zuul") + headers.set(X_ZUUL_INSTANCE, INSTANCE_ID.get() ?: "unknown") + headers.set(CONNECTION, KEEP_ALIVE) + headers.set(X_ORIGINATING_URL, response.getInboundRequest().reconstructURI()) + + if (response.getStatus() >= 400 && context.getError() != null) { + Throwable error = context.getError() + headers.set(X_ZUUL_ERROR_CAUSE, + error instanceof ZuulException ? ((ZuulException) error).getErrorCause() : error.toString()) + } + + if (response.getStatus() >= 500) { + logger.info("Passport: {}", CurrentPassport.fromSessionContext(context)) + } + + if (logger.isDebugEnabled()) { + logger.debug("Filter execution summary :: {}", context.getFilterExecutionSummary()) + } + } + + if (context.debugRequest()) { + Debug.getRequestDebug(context).forEach({ s -> logger.info("REQ_DEBUG: " + s) }) + Debug.getRoutingDebug(context).forEach({ s -> logger.info("ZUUL_DEBUG: " + s) }) + } + + return response + } +} diff --git a/api-gateway/src/main/java/com/egommerce/apigateway/ApiGwServerStartup.java b/api-gateway/src/main/java/com/egommerce/apigateway/ApiGwServerStartup.java new file mode 100644 index 0000000..34b2a76 --- /dev/null +++ b/api-gateway/src/main/java/com/egommerce/apigateway/ApiGwServerStartup.java @@ -0,0 +1,234 @@ +package com.egommerce.apigateway; + +import java.io.File; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.egommerce.apigateway.module.ApiGwFiltersModule; +import com.netflix.appinfo.ApplicationInfoManager; +import com.netflix.config.DynamicIntProperty; +import com.netflix.config.DynamicStringProperty; +import com.netflix.discovery.EurekaClient; +import com.netflix.netty.common.accesslog.AccessLogPublisher; +import com.netflix.netty.common.channel.config.ChannelConfig; +import com.netflix.netty.common.channel.config.ChannelConfigValue; +import com.netflix.netty.common.channel.config.CommonChannelConfigKeys; +import com.netflix.netty.common.metrics.EventLoopGroupMetrics; +import com.netflix.netty.common.proxyprotocol.StripUntrustedProxyHeadersHandler; +import com.netflix.netty.common.ssl.ServerSslConfig; +import com.netflix.netty.common.status.ServerStatusManager; +import com.netflix.spectator.api.Registry; +import com.netflix.zuul.FilterLoader; +import com.netflix.zuul.FilterUsageNotifier; +import com.netflix.zuul.RequestCompleteHandler; +import com.netflix.zuul.context.SessionContextDecorator; +import com.netflix.zuul.netty.server.BaseServerStartup; +import com.netflix.zuul.netty.server.DirectMemoryMonitor; +import com.netflix.zuul.netty.server.NamedSocketAddress; +import com.netflix.zuul.netty.server.SocketAddressProperty; +import com.netflix.zuul.netty.server.ZuulServerChannelInitializer; +import com.netflix.zuul.netty.server.http2.Http2SslChannelInitializer; +import com.netflix.zuul.netty.ssl.BaseSslContextFactory; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.group.ChannelGroup; +import io.netty.handler.ssl.ClientAuth; + +/** + * ApiGw Server Startup - class that configures the Netty server startup settings + */ +@Singleton +public class ApiGwServerStartup extends BaseServerStartup { + private static final Logger log = LoggerFactory.getLogger(ApiGwFiltersModule.class); + + enum ServerType { + HTTP, + HTTP2, + // HTTP_MUTUAL_TLS, + } + + private static final String[] WWW_PROTOCOLS = new String[]{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"}; + private static final ServerType SERVER_TYPE = ServerType.HTTP2; + + @Inject + public ApiGwServerStartup(ServerStatusManager serverStatusManager, FilterLoader filterLoader, + SessionContextDecorator sessionCtxDecorator, FilterUsageNotifier usageNotifier, + RequestCompleteHandler reqCompleteHandler, Registry registry, + DirectMemoryMonitor directMemoryMonitor, EventLoopGroupMetrics eventLoopGroupMetrics, + EurekaClient discoveryClient, ApplicationInfoManager applicationInfoManager, + AccessLogPublisher accessLogPublisher) { + super(serverStatusManager, filterLoader, sessionCtxDecorator, usageNotifier, reqCompleteHandler, registry, + directMemoryMonitor, eventLoopGroupMetrics, discoveryClient, applicationInfoManager, accessLogPublisher); + log.info("API-GATEWAY:Startup: Initialization..."); + + // Call PostConstruct by hand, cause inject.*.PostConstruct annotation issue... + PostConstruct(); + } + + public void PostConstruct() { + log.debug("API-DATEWAY:Startup: PostConstruct"); + try { + init(); + } catch (Exception e) { + log.error("Failed to server netty server. Quitting."); + } + } + + @Override + protected Map> chooseAddrsAndChannels(ChannelGroup clientChannels) { + Map> addrsToChannels = new HashMap<>(); + + try { + int port = new DynamicIntProperty("zuul.server.port", 8000).get(); + String addr = new DynamicStringProperty("zuul.server.addr", "127.0.0.1").get(); + SocketAddress sockAddr = new SocketAddressProperty(addr, "=" + port).getValue(); + String metricId = sockAddr.toString(); + if (sockAddr instanceof InetSocketAddress) { + metricId = String.valueOf(((InetSocketAddress) sockAddr).getPort()); + } + // log.debug("API-GATEWAY:chooseAddrsAndChannels:$metricId: " +metricId); + + String mainListenAddressName = "main"; + ServerSslConfig sslConfig; + ChannelConfig channelConfig = defaultChannelConfig(mainListenAddressName); + ChannelConfig channelDependencies = defaultChannelDependencies(mainListenAddressName); + + /* These settings may need to be tweaked depending if you're running behind an ELB HTTP listener, TCP listener, + * or directly on the internet. + */ + switch (SERVER_TYPE) { + /* The below settings can be used when running behind an ELB HTTP listener that terminates SSL for you + * and passes XFF headers. + */ + case HTTP: + channelConfig.set(CommonChannelConfigKeys.allowProxyHeadersWhen, StripUntrustedProxyHeadersHandler.AllowWhen.ALWAYS); + channelConfig.set(CommonChannelConfigKeys.preferProxyProtocolForClientIp, false); + channelConfig.set(CommonChannelConfigKeys.isSSlFromIntermediary, false); + channelConfig.set(CommonChannelConfigKeys.withProxyProtocol, false); + + logAddrConfigured(sockAddr); + addrsToChannels.put( + new NamedSocketAddress("http", sockAddr), + new ZuulServerChannelInitializer(metricId, channelConfig, channelDependencies, clientChannels) + ); + break; + + /* The below settings can be used when running behind an ELB TCP listener with proxy protocol, terminating + * SSL in Zuul. + */ + case HTTP2: + // sslConfig = new ServerSslConfig( + // WWW_PROTOCOLS, + // ServerSslConfig.getDefaultCiphers(), + // loadFromResources("ssl/api-gateway-svc.cert"), + // loadFromResources("ssl/api-gateway-svc-pem.key"), + // ClientAuth.NONE + // ); + sslConfig = ServerSslConfig.withDefaultCiphers( + loadFromResources("ssl/api-gateway-svc.cert"), + loadFromResources("ssl/api-gateway-svc.pem"), + WWW_PROTOCOLS + ); + + channelConfig.set(CommonChannelConfigKeys.allowProxyHeadersWhen, StripUntrustedProxyHeadersHandler.AllowWhen.NEVER); + channelConfig.set(CommonChannelConfigKeys.preferProxyProtocolForClientIp, true); + channelConfig.set(CommonChannelConfigKeys.withProxyProtocol, true); + channelConfig.set(CommonChannelConfigKeys.isSSlFromIntermediary, false); + channelConfig.set(CommonChannelConfigKeys.serverSslConfig, sslConfig); + channelConfig.set(CommonChannelConfigKeys.sslContextFactory, new BaseSslContextFactory(registry, sslConfig)); + + // channelConfig.set(ChannelOption.SO_KEEPALIVE, true); + // channelConfig.set(ChannelOption.TCP_NODELAY, true); + // channelConfig.set(ChannelOption., ); + + addHttp2DefaultConfig(channelConfig, String.valueOf(port)); + + logAddrConfigured(sockAddr, sslConfig); + addrsToChannels.put(new NamedSocketAddress("https", sockAddr), new Http2SslChannelInitializer(metricId, channelConfig, channelDependencies, clientChannels)); + break; + + /* The below settings can be used when running behind an ELB TCP listener with proxy protocol, terminating + * SSL in Zuul. + * + * Can be tested using certs in resources directory: + * curl https://localhost:7001/test -vk --cert src/main/resources/ssl/client.cert:zuul123 --key src/main/resources/ssl/client.key + */ + // case HTTP_MUTUAL_TLS: + // sslConfig = new ServerSslConfig( + // WWW_PROTOCOLS, + // ServerSslConfig.getDefaultCiphers(), + // loadFromResources("server.cert"), + // loadFromResources("server.key"), + // // null, + // ClientAuth.REQUIRE, + // loadFromResources("truststore.jks"), + // loadFromResources("truststore.key"), + // false); + + // channelConfig.set(CommonChannelConfigKeys.allowProxyHeadersWhen, StripUntrustedProxyHeadersHandler.AllowWhen.NEVER); + // channelConfig.set(CommonChannelConfigKeys.preferProxyProtocolForClientIp, true); + // channelConfig.set(CommonChannelConfigKeys.isSSlFromIntermediary, false); + // channelConfig.set(CommonChannelConfigKeys.withProxyProtocol, true); + // channelConfig.set(CommonChannelConfigKeys.serverSslConfig, sslConfig); + // channelConfig.set(CommonChannelConfigKeys.sslContextFactory, new BaseSslContextFactory(registry, sslConfig)); + + // addrsToChannels.put(new NamedSocketAddress("http_mtls", sockAddr), new Http1MutualSslChannelInitializer(metricId, channelConfig, channelDependencies, clientChannels)); + // logAddrConfigured(sockAddr, sslConfig); + // break; + } + + log.debug("$addrsToChannel:", addrsToChannels); + // Class s = server.getClass(); + // for (Method method : s.getDeclaredMethods()) { + // log.debug(method.getName()); + // } + } catch (Exception e) { + log.error("Startup::Exception: " + e.getMessage()); + for (StackTraceElement tr : e.getStackTrace()) { + log.error(tr.toString()); + } + } + + return addrsToChannels; + } + + // public static void addHttp2DefaultConfig(ChannelConfig config, String listenAddressName) { + // config.add(new ChannelConfigValue<>(CommonChannelConfigKeys.maxConcurrentStreams, + // chooseIntChannelProperty( + // listenAddressName, + // "http2.max.concurrent.streams", + // CommonChannelConfigKeys.maxConcurrentStreams.defaultValue()))); + // config.add(new ChannelConfigValue<>(CommonChannelConfigKeys.initialWindowSize, + // chooseIntChannelProperty( + // listenAddressName, + // "http2.initialwindowsize", + // CommonChannelConfigKeys.initialWindowSize.defaultValue()))); + // config.add(new ChannelConfigValue<>(CommonChannelConfigKeys.maxHttp2HeaderTableSize, + // chooseIntChannelProperty(listenAddressName, "http2.maxheadertablesize", 65536))); + // config.add(new ChannelConfigValue<>(CommonChannelConfigKeys.maxHttp2HeaderListSize, + // chooseIntChannelProperty(listenAddressName, "http2.maxheaderlistsize", 32768))); + + // // Override this to a lower value, as we'll be using ELB TCP listeners for h2, and therefore the connection + // // is direct from each device rather than shared in an ELB pool. + // config.add(new ChannelConfigValue<>(CommonChannelConfigKeys.maxRequestsPerConnection, + // chooseIntChannelProperty(listenAddressName, "connection.max.requests", 4000))); + + // config.add(new ChannelConfigValue<>(CommonChannelConfigKeys.http2AllowGracefulDelayed, + // chooseBooleanChannelProperty(listenAddressName, "connection.close.graceful.delayed.allow", true))); + // config.add(new ChannelConfigValue<>(CommonChannelConfigKeys.http2SwallowUnknownExceptionsOnConnClose, + // chooseBooleanChannelProperty(listenAddressName, "connection.close.swallow.unknown.exceptions", false))); + // } + + private File loadFromResources(String s) { + return new File(ClassLoader.getSystemResource(s).getFile()); + } +} diff --git a/api-gateway/src/main/java/com/egommerce/apigateway/ApiGwServerStatusManager.java b/api-gateway/src/main/java/com/egommerce/apigateway/ApiGwServerStatusManager.java new file mode 100644 index 0000000..8953e34 --- /dev/null +++ b/api-gateway/src/main/java/com/egommerce/apigateway/ApiGwServerStatusManager.java @@ -0,0 +1,20 @@ +package com.egommerce.apigateway; +// package com.egommerce.apigw; + +// import com.netflix.appinfo.ApplicationInfoManager; +// import com.netflix.discovery.DiscoveryClient; +// import com.netflix.netty.common.status.ServerStatusManager; + +// import javax.inject.Inject; +// import javax.inject.Singleton; + +// @Singleton +// public class ApiGwServerStatusManager extends ServerStatusManager +// { +// @Inject +// public ApiGwServerStatusManager(ApplicationInfoManager applicationInfoManager/*, DiscoveryClient discoveryClient*/) { +// super(applicationInfoManager/* , discoveryClient*/); +// // System.out.println(discoveryClient); +// // System.exit(1); +// } +// } diff --git a/api-gateway/src/main/java/com/egommerce/apigateway/Bootstrap.java b/api-gateway/src/main/java/com/egommerce/apigateway/Bootstrap.java new file mode 100644 index 0000000..29ade25 --- /dev/null +++ b/api-gateway/src/main/java/com/egommerce/apigateway/Bootstrap.java @@ -0,0 +1,53 @@ +package com.egommerce.apigateway; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.netflix.zuul.netty.server.BaseServerStartup; +import com.netflix.zuul.netty.server.Server; + +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// import io.netty.handler.codec.http.DefaultHttpRequest; +import com.netflix.zuul.filters.endpoint.ProxyEndpoint; + +public class Bootstrap { + private static final Logger logger = LoggerFactory.getLogger(Bootstrap.class); + + public static void main(String[] args) { + new Bootstrap().start(); + } + + public void start() { + long startNanos = System.nanoTime(); + logger.info("###############"); + logger.info("Starting up..."); + int exitCode = 0; + + Server server = null; + + try { + Injector injector = Guice.createInjector(new ZuulApiGwModule()); + BaseServerStartup serverStartup = injector.getInstance(BaseServerStartup.class); + server = serverStartup.server(); + server.start(); + + long startupDuration = System.nanoTime() - startNanos; + logger.info("Finished startup. Duration = {}s", TimeUnit.NANOSECONDS.toSeconds(startupDuration)); + server.awaitTermination(); + } catch (Throwable t) { + t.printStackTrace(); + logger.error("Initialization failed. Forcing shutdown now..."); + exitCode = 1; + } finally { + if (server != null) { + server.stop(); + } + logger.info("Shutdown completed. Quiting."); + logger.info("###############"); + + System.exit(exitCode); + } + } +} diff --git a/api-gateway/src/main/java/com/egommerce/apigateway/ZuulApiGwModule.java b/api-gateway/src/main/java/com/egommerce/apigateway/ZuulApiGwModule.java new file mode 100644 index 0000000..3064f78 --- /dev/null +++ b/api-gateway/src/main/java/com/egommerce/apigateway/ZuulApiGwModule.java @@ -0,0 +1,86 @@ +package com.egommerce.apigateway; + +// import com.egommerce.apigateway.config.ApiGwServerSslConfig; +import com.egommerce.apigateway.module.ApiGwEurekaModule; +import com.egommerce.apigateway.module.ApiGwFiltersModule; +import com.google.inject.AbstractModule; +import com.netflix.config.ConfigurationManager; +import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs; +import com.netflix.discovery.DiscoveryClient; +import com.netflix.discovery.shared.resolver.EndpointRandomizer; +import com.netflix.discovery.shared.resolver.ResolverUtils; +import com.netflix.netty.common.accesslog.AccessLogPublisher; +import com.netflix.netty.common.ssl.ServerSslConfig; +import com.netflix.netty.common.status.ServerStatusManager; +import com.netflix.spectator.api.DefaultRegistry; +import com.netflix.spectator.api.Registry; +import com.netflix.zuul.BasicRequestCompleteHandler; +import com.netflix.zuul.DynamicCodeCompiler; +import com.netflix.zuul.DynamicFilterLoader; +import com.netflix.zuul.FilterFileManager; +import com.netflix.zuul.FilterLoader; +import com.netflix.zuul.RequestCompleteHandler; +import com.netflix.zuul.context.SessionContextDecorator; +import com.netflix.zuul.context.ZuulSessionContextDecorator; +import com.netflix.zuul.filters.FilterRegistry; +import com.netflix.zuul.filters.MutableFilterRegistry; +import com.netflix.zuul.groovy.GroovyCompiler; +import com.netflix.zuul.groovy.GroovyFileFilter; +import com.netflix.zuul.netty.server.BaseServerStartup; +import com.netflix.zuul.netty.server.ClientRequestReceiver; +import com.netflix.zuul.origins.BasicNettyOriginManager; +import com.netflix.zuul.origins.OriginManager; +import com.netflix.zuul.stats.BasicRequestMetricsPublisher; +import com.netflix.zuul.stats.RequestMetricsPublisher; +import java.io.FilenameFilter; +import org.apache.commons.configuration.AbstractConfiguration; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; + +public class ZuulApiGwModule extends AbstractModule { + // private static final Logger log = LoggerFactory.getLogger(ZuulApiGwModule.class); + + @Override + protected void configure() { + try { + ConfigurationManager.loadCascadedPropertiesFromResources("application"); + } catch (Exception ex) { + throw new RuntimeException("Error loading configuration: " + ex.getMessage(), ex); + } + + bind(AbstractConfiguration.class).toInstance(ConfigurationManager.getConfigInstance()); + bind(DynamicCodeCompiler.class).to(GroovyCompiler.class); + bind(FilenameFilter.class).to(GroovyFileFilter.class); + + // bind(ServerSslConfig.class).to(ApiGwServerSslConfig.class); + + // zuul eureka module + bind(EndpointRandomizer.class).toInstance(ResolverUtils::randomize); + install(new ApiGwEurekaModule()); + + // server specific bindings + bind(BaseServerStartup.class).to(ApiGwServerStartup.class); + // use provided basic netty origin manager + bind(OriginManager.class).to(BasicNettyOriginManager.class); + + // general server bindings + bind(ServerStatusManager.class); // health/discovery status + bind(SessionContextDecorator.class).to(ZuulSessionContextDecorator.class); // decorate new sessions when requests come in + bind(Registry.class).to(DefaultRegistry.class); // atlas metrics registry + bind(RequestCompleteHandler.class).to(BasicRequestCompleteHandler.class); // metrics post-request completion + bind(AbstractDiscoveryClientOptionalArgs.class).to(DiscoveryClient.DiscoveryClientOptionalArgs.class); // discovery client + bind(RequestMetricsPublisher.class).to(BasicRequestMetricsPublisher.class); // timings publisher + + // zuul filter loading + install(new ApiGwFiltersModule()); + bind(FilterLoader.class).to(DynamicFilterLoader.class); + bind(FilterRegistry.class).to(MutableFilterRegistry.class); + bind(FilterFileManager.class).asEagerSingleton(); + + + // access logger, including request ID generator + bind(AccessLogPublisher.class).toInstance(new AccessLogPublisher("ACCESS", + (channel, httpRequest) -> ClientRequestReceiver.getRequestFromChannel(channel).getContext().getUUID()) + ); + } +} diff --git a/api-gateway/src/main/java/com/egommerce/apigateway/config/ApiGwServerSslConfig.java b/api-gateway/src/main/java/com/egommerce/apigateway/config/ApiGwServerSslConfig.java new file mode 100644 index 0000000..a673764 --- /dev/null +++ b/api-gateway/src/main/java/com/egommerce/apigateway/config/ApiGwServerSslConfig.java @@ -0,0 +1,18 @@ +// package com.egommerce.apigateway.config; + +// import java.io.File; + +// import com.netflix.netty.common.ssl.ServerSslConfig; + +// import io.netty.handler.ssl.ClientAuth; + +// public class ApiGwServerSslConfig extends ServerSslConfig { + +// public ApiGwServerSslConfig( +// String[] protocols, String[] ciphers, File certChainFile, File keyFile, ClientAuth clientAuth, +// File clientAuthTrustStoreFile, File clientAuthTrustStorePasswordFile, boolean sessionTicketsEnabled) { +// super(protocols, ciphers, certChainFile, keyFile, ClientAuth.NONE, getCertChainFile(), getClientAuthTrustStorePassword(), sessionTicketsEnabled) + +// this.clientAuthTrustStorePassword = null; +// } +// } diff --git a/api-gateway/src/main/java/com/egommerce/apigateway/module/ApiGwEurekaModule.java b/api-gateway/src/main/java/com/egommerce/apigateway/module/ApiGwEurekaModule.java new file mode 100644 index 0000000..1844106 --- /dev/null +++ b/api-gateway/src/main/java/com/egommerce/apigateway/module/ApiGwEurekaModule.java @@ -0,0 +1,43 @@ +package com.egommerce.apigateway.module; + +import com.google.inject.AbstractModule; +import com.google.inject.Scopes; +import com.netflix.appinfo.ApplicationInfoManager; +import com.netflix.appinfo.EurekaInstanceConfig; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.appinfo.MyDataCenterInstanceConfig; +import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider; +import com.netflix.discovery.DiscoveryClient; +import com.netflix.discovery.DefaultEurekaClientConfig; +import com.netflix.discovery.EurekaClient; +import com.netflix.discovery.EurekaClientConfig; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; + +public class ApiGwEurekaModule extends AbstractModule { + // private static final Logger log = LoggerFactory.getLogger(ApiGwFiltersModule.class); + + @Override + protected void configure() { + // need to eagerly initialize + bind(ApplicationInfoManager.class).asEagerSingleton(); + bind(EurekaClient.class).to(DiscoveryClient.class).in(Scopes.SINGLETON); + + bind(EurekaInstanceConfig.class).to(MyDataCenterInstanceConfig.class); + bind(EurekaClientConfig.class).to(DefaultEurekaClientConfig.class); + // bind(EurekaClientConfig.class).toProvider(DefaultEurekaClientConfigProvider.class).in(Scopes.SINGLETON); + + // // this is the self instanceInfo used for registration purposes + bind(InstanceInfo.class).toProvider(EurekaConfigBasedInstanceInfoProvider.class).in(Scopes.SINGLETON); + } + + @Override + public boolean equals(Object obj) { + return obj != null && getClass().equals(obj.getClass()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/api-gateway/src/main/java/com/egommerce/apigateway/module/ApiGwFiltersModule.java b/api-gateway/src/main/java/com/egommerce/apigateway/module/ApiGwFiltersModule.java new file mode 100644 index 0000000..0b97ced --- /dev/null +++ b/api-gateway/src/main/java/com/egommerce/apigateway/module/ApiGwFiltersModule.java @@ -0,0 +1,109 @@ +package com.egommerce.apigateway.module; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.reflect.ClassPath; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.netflix.zuul.BasicFilterUsageNotifier; +import com.netflix.zuul.FilterFactory; +import com.netflix.zuul.FilterFileManager.FilterFileManagerConfig; +import com.netflix.zuul.FilterUsageNotifier; +import com.netflix.zuul.filters.ZuulFilter; +import com.netflix.zuul.guice.GuiceFilterFactory; +import java.io.FilenameFilter; +import org.apache.commons.configuration.AbstractConfiguration; + +import java.io.IOException; +import java.util.Arrays; +import java.util.function.Predicate; +import java.util.stream.Stream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ApiGwFiltersModule extends AbstractModule { + private static final Logger log = LoggerFactory.getLogger(ApiGwFiltersModule.class); + + private static Predicate blank = String::isEmpty; + + @Override + protected void configure() { + log.info("Starting Groovy Filter file manager"); + + bind(FilterFactory.class).to(GuiceFilterFactory.class); + bind(FilterUsageNotifier.class).to(BasicFilterUsageNotifier.class); + + log.info("Groovy Filter file manager started"); + } + + @Provides + FilterFileManagerConfig provideFilterFileManagerConfig( + AbstractConfiguration config, FilenameFilter filenameFilter) { + // Get filter directories. + String[] filterLocations = findFilterLocations(config); + String[] filterClassNames = findClassNames(config); + + // Init the FilterStore. + FilterFileManagerConfig filterConfig = + new FilterFileManagerConfig(filterLocations, filterClassNames, 5, filenameFilter); + return filterConfig; + } + + // Get compiled filter classes to be found on classpath. + @VisibleForTesting + String[] findClassNames(AbstractConfiguration config) { + + // Find individually-specified filter classes. + String[] filterClassNamesStrArray = config.getStringArray("zuul.filters.classes"); + Stream classNameStream = Arrays.stream(filterClassNamesStrArray) + .map(String::trim) + .filter(blank.negate()); + + // Find filter classes in specified packages. + String[] packageNamesStrArray = config.getStringArray("zuul.filters.packages"); + ClassPath cp; + try { + cp = ClassPath.from(this.getClass().getClassLoader()); + } + catch (IOException e) { + throw new RuntimeException("Error attempting to read classpath to find filters!", e); + } + Stream packageStream = Arrays.stream(packageNamesStrArray) + .map(String::trim) + .filter(blank.negate()) + .flatMap(packageName -> cp.getTopLevelClasses(packageName).stream()) + .map(ClassPath.ClassInfo::load) + .filter(ZuulFilter.class::isAssignableFrom) + .map(Class::getCanonicalName); + + + String[] filterClassNames = Stream.concat(classNameStream, packageStream).toArray(String[]::new); + if (filterClassNames.length != 0) { + log.info("Using filter classnames: "); + for (String location : filterClassNames) { + log.info(" " + location); + } + } + + return filterClassNames; + } + + @VisibleForTesting + String[] findFilterLocations(AbstractConfiguration config) { + String[] locations = config.getStringArray("zuul.filters.locations"); + if (locations == null) { + locations = new String[]{"inbound", "outbound", "endpoint"}; + } + String[] filterLocations = Arrays.stream(locations) + .map(String::trim) + .filter(blank.negate()) + .toArray(String[]::new); + + if (filterLocations.length != 0) { + log.info("Using filter locations: "); + for (String location : filterLocations) { + log.info(" " + location); + } + } + return filterLocations; + } +} diff --git a/api-gateway/src/main/resources/application.properties b/api-gateway/src/main/resources/application.properties new file mode 100644 index 0000000..ff704e2 --- /dev/null +++ b/api-gateway/src/main/resources/application.properties @@ -0,0 +1,164 @@ +# shortcuts +api_eureka_port=8761 +# end: shortcuts + +# dev mode +zuul.responseFilter.send.headers=true + +# STABLE +zuul.server.port=8443 +zuul.server.addr=127.0.0.1 + +# Loading filters +zuul.filters.root=src/main/groovy/com/egommerce/apigateway/filters +zuul.filters.locations=${zuul.filters.root}/inbound,${zuul.filters.root}/outbound,${zuul.filters.root}/endpoint +zuul.filters.packages=com.netflix.zuul.filters.common + +# Eureka configuration +# eureka api registry svc url +eureka.serviceUrl.default=http://127.0.0.1:${api_eureka_port}/eureka/ + +eureka.region=default + +# fetch registry from eureka service +eureka.shouldFetchRegistry=true +# register instance in eureka service +eureka.registration.enabled=true + +eureka.validateInstanceId=false +eureka.preferSameZone=true +eureka.shouldUseDns=false + +# Test +# api-gateway-svc.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList +ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList + +api-gateway-svc.ribbon.DeploymentContextBasedVipAddresses=api-gateway-svc + +identity-svc.ribbon.DeploymentContextBasedVipAddresses=identity-svc +identity-svc.ribbon.IsSecure=true + +# api.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList +# api.ribbon.DeploymentContextBasedVipAddresses=identity-svc + +# eureka.shouldFilterOnlyUpInstance=false +# eureka.shouldOnDemandUpdateStatusChange=false + +# Ribbon +# ribbon.eureka.enabled=true + + +# api.ribbon.listOfServers=identity-svc:8080 +# api.ribbon.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList +# api.client.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList + +# api.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList +# api.ribbon.DeploymentContextBasedVipAddresses=identity-svc + +# ribbon.listOfServers=127.0.0.1:8761 +# ribbon.DeploymentContextBasedVipAddresses="other-path:443" +# ribbon.listOfServers=127.0.0.1:9999 +# ribbon.client.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList +# ribbon.DeploymentContextBasedVipAddresses=${eureka.vipAddress} +# ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList +# ribbon.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList +# ribbon.DeploymentContextBasedVipAddresses=${zuul.server.addr}:${zuul.server.port} + + +# eureka.virtualHostName=${eureka.name} +# eureka.nonSecurePortEnabled=true +# eureka.nonSecurePort={$eureka.port} +# eureka.securePortEnabled=false +# eureka.securePort={$eureka.port} + +# eureka.instance.virtualHostName=${eureka.name} +# eureka.instance.nonSecurePortEnabled=true +# eureka.instance.nonSecurePort={$eureka.port} +# eureka.instance.securePortEnabled=false +# eureka.instance.securePort={$eureka.port} +# eureka.instance.secureVirtualHostName=${eureka.name} + +# eureka.client.fetchRegistry=true +# eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://127.0.0.1:8761/eureka} +# eureka.serviceUrl.defaultZone=${eureka.serviceUrl.default} +# eureka.client.serviceUrl.defaultZone=${eureka.serviceUrl.default} + + +# store routes in config.properties ... + +# zuul.retryable=true + +# zuul.http2.enabled=true + +# SSL configuration +# zuul.ssl.enabled=true +# zuul.ssl.protocol=TLS +# zuul.ssl.keyAlias=${spring.application.name} +# zuul.ssl.keyStore=classpath:keystore.p12 +# zuul.ssl.keyStoreType=PKCS12 +# zuul.ssl.keyStorePassword=${KEYSTORE_PASSWORD} +# zuul.ssl.keyPassword=${KEYSTORE_PASSWORD} +# zuul.ssl.trustStore=classpath:truststore.p12 +# zuul.ssl.trustStoreType=PKCS12 +# zuul.ssl.trustStorePassword=${KEYSTORE_PASSWORD} +# zuul.ssl.hostnameValidationEnabled=false + +# Timeouts configuration +# zuul.host.socketTimeoutMillis=10000 +# zuul.host.connectTimeoutMillis=10000 +# zuul.host.maxTotalConnections=5000 +# zuul.host.maxPerRouteConnections=5 + + +# Ribbon configuration + +# ribbon.okhttp.enabled=true + +# ribbon: +# ReadTimeout: 20000 +# ConnectTimeout: 20000 +# MaxAutoRetries: 0 +# MaxAutoRetriesNextServer: 1 +# MaxTotalHttpConnections: 2000 +# MaxConnectionsPerHost: 1000 + + +# Routing to proxied backend services +# api.ribbon.port=8761 +# api.ribbon.ReadTimeout: 9999 +# api.ribbon.ConnectTimeout: 8888 +# api.ribbon.MaxAutoRetries: 5 +# api.ribbon.MaxAutoRetriesNextServer: 6 +# api.ribbon.MaxTotalHttpConnections: 7777 +# api.ribbon.MaxConnectionsPerHost: 6666 + + + +# management: # debug +# endpoints: +# web: +# exposure: +# include: +# - "*" + +# ribbon: +# eureka: +# enabled: true +# okhttp: +# enabled: true +# ReadTimeout: 20000 +# ConnectTimeout: 20000 +# MaxAutoRetries: 0 +# MaxAutoRetriesNextServer: 1 +# MaxTotalHttpConnections: 2000 +# MaxConnectionsPerHost: 1000 + +# hystrix: +# command: +# default: +# execution: +# timeout: +# enabled: false +# isolation: +# thread: +# timeoutInMilliseconds: 60000 diff --git a/api-gateway/src/main/resources/config.properties b/api-gateway/src/main/resources/config.properties new file mode 100644 index 0000000..7847e42 --- /dev/null +++ b/api-gateway/src/main/resources/config.properties @@ -0,0 +1,13 @@ +zuul.routes.identity-svc.path=/auth/** +zuul.routes.identity-svc.serviceId=identity-svc +# zuul.routes.identity-svc.url=grpc://127.0.0.1:8080/ + +#zuul.routes.api-gateway-svc.path=/gateway/** +#zuul.routes.api-gateway-svc.serviceId=api-dateway-svc + +#zuul.routes.identity-svc.path=/AuthService/** +#zuul.routes.identity-svc.url=http://127.0.0.1:9999/auth/ + +#zuul.routes.basket-svc.path=/BasketService/** +#zuul.routes.basket-svc.serviceId=basket-svc + \ No newline at end of file diff --git a/api-gateway/src/main/resources/eureka-client.properties b/api-gateway/src/main/resources/eureka-client.properties new file mode 100644 index 0000000..feaaee9 --- /dev/null +++ b/api-gateway/src/main/resources/eureka-client.properties @@ -0,0 +1,18 @@ +# Client registratio config + +eureka.name=api-gateway-svc +eureka.instanceId=api-gateway-svc + +eureka.app=api-gateway-svc +# eureka.hostName=api-gateway-svc-hostname +eureka.appGroup=egommerce +eureka.vipAddress=api-gateway-svc + +eureka.port=8000 +eureka.port.enabled=true +eureka.securePort=8443 +eureka.securePort.enabled=false + +eureka.homePageUrl=http://${zuul.server.addr}:${zuul.server.port}/API +eureka.statusPageUrl=http://${zuul.server.addr}:${zuul.server.port}/API/status +eureka.healthCheckUrl=http://${zuul.server.addr}:${zuul.server.port}/API/healthcheck \ No newline at end of file diff --git a/api-gateway/src/main/resources/simplelogger.properties b/api-gateway/src/main/resources/simplelogger.properties new file mode 100644 index 0000000..cc9afaa --- /dev/null +++ b/api-gateway/src/main/resources/simplelogger.properties @@ -0,0 +1,30 @@ +org.slf4j.simpleLogger.defaultLogLevel=debug +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z +org.slf4j.simpleLogger.showThreadName=true + +log4j.rootLogger=debug, STDOUT +log4j.logger.deng=debug +rootLogger.level = debug + +# log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender +# log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout +# log4j.appender.STDOUT.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n + +# rootLogger.appenderRef.stdout.ref = STDOUT + +# log4j.logger.com.netflix.loadbalancer=debug +# log4j.logger.com.netflix.config=debug +# log4j.logger.com.egommerce.apigw=debug +# log4j.logger.com.egommerce.apigw.level=debug +# log4j.logger.com.egommerce.apigw.module.level=debug + +# # log4j.appender.R=org.apache.log4j.RollingFileAppender +# # log4j.appender.R.File=example.log + +# # log4j.appender.R.MaxFileSize=100KB +# # # Keep one backup file +# # log4j.appender.R.MaxBackupIndex=1 + +# # log4j.appender.R.layout=org.apache.log4j.PatternLayout +# # log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n diff --git a/api-gateway/src/main/resources/ssl/api-gateway-svc.cert b/api-gateway/src/main/resources/ssl/api-gateway-svc.cert new file mode 100644 index 0000000..e430225 --- /dev/null +++ b/api-gateway/src/main/resources/ssl/api-gateway-svc.cert @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/api-gateway/src/main/resources/ssl/api-gateway-svc.key b/api-gateway/src/main/resources/ssl/api-gateway-svc.key new file mode 100644 index 0000000..be6cab5 --- /dev/null +++ b/api-gateway/src/main/resources/ssl/api-gateway-svc.key @@ -0,0 +1,54 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +gi9AIDRe7xUKIxlzjYTJbw== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/api-gateway/src/main/resources/ssl/api-gateway-svc.pem b/api-gateway/src/main/resources/ssl/api-gateway-svc.pem new file mode 100644 index 0000000..d11fa6c --- /dev/null +++ b/api-gateway/src/main/resources/ssl/api-gateway-svc.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +30ORlCczdDMlDQoGa9jOX7k1R34fxCU= +-----END PRIVATE KEY----- diff --git a/apigw/.gitignore b/apigw/.gitignore deleted file mode 100644 index 549e00a..0000000 --- a/apigw/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/apigw/.mvn/wrapper/maven-wrapper.jar b/apigw/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index c1dd12f..0000000 Binary files a/apigw/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/apigw/.mvn/wrapper/maven-wrapper.properties b/apigw/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index b74bf7f..0000000 --- a/apigw/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/apigw/pom.xml b/apigw/pom.xml deleted file mode 100644 index 1cc8f47..0000000 --- a/apigw/pom.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - 4.0.0 - com.egommerce - api-gw - 0.0.1-SNAPSHOT - api-gw - Egommerce API Gateway - Based on Netflix Zuul - - - org.springframework.cloud - spring-cloud-starter-netflix - 2.2.10.RELEASE - - - - 18 - 1.8 - 1.8 - UTF-8 - 2.7.4 - 2021.0.4 - - - - - - org.springframework.boot - spring-boot-starter-parent - 2.7.4 - - - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-starter-netflix-zuul - 2.2.10.RELEASE - - - org.springframework.boot - spring-boot-starter-test - - - - - - - src/main/resources - true - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/apigw/src/main/java/com/egommerce/apigw/ApigwApplication.java b/apigw/src/main/java/com/egommerce/apigw/ApigwApplication.java deleted file mode 100644 index 0c1a437..0000000 --- a/apigw/src/main/java/com/egommerce/apigw/ApigwApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.egommerce.apigw; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.netflix.zuul.EnableZuulProxy; - -@EnableZuulProxy -@SpringBootApplication -public class ApigwApplication { - - public static void main(String[] args) { - SpringApplication.run(ApigwApplication.class, args); - } -} diff --git a/apigw/src/main/resources/application.yml b/apigw/src/main/resources/application.yml deleted file mode 100644 index 6e6ad40..0000000 --- a/apigw/src/main/resources/application.yml +++ /dev/null @@ -1,16 +0,0 @@ -zuul: - routes: - auth: - path: /auth/** - url: http://identity_svc:8080/ - -# zuul: -# routes: -# identity: -# service-id: '/identity/**' -# path: '/auth/**' -# url: 'http://identity_svc:8080/' - - -server: - port: 12345 diff --git a/apigw/src/test/java/com/egommerce/apigw/ApigwApplicationTests.java b/apigw/src/test/java/com/egommerce/apigw/ApigwApplicationTests.java deleted file mode 100644 index 77be8d6..0000000 --- a/apigw/src/test/java/com/egommerce/apigw/ApigwApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.egommerce.apigw; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class ApigwApplicationTests { - - // @Test - // void contextLoads() { - // } - -} diff --git a/deploy/image-build.sh b/deploy/image-build.sh index 2e4a1be..b65b899 100755 --- a/deploy/image-build.sh +++ b/deploy/image-build.sh @@ -1,8 +1,7 @@ #!/bin/sh # RUN IN REPO ROOT DIR !! -export IMAGE_NAME="git.pbiernat.dev/egommerce/apigw-svc" - +IMAGE_NAME="git.pbiernat.dev/egommerce/apigw-svc" TARGET=${1:-latest} echo "Building: $IMAGE_NAME:$TARGET" @@ -10,7 +9,7 @@ if [ $TARGET = "latest" ] then docker build --rm --cache-from "$IMAGE_NAME:$TARGET" -t "$IMAGE_NAME:$TARGET" else - docker build --rm --no-cache -t "$IMAGE_NAME:$TARGET" . >/dev/null 2>&1 + docker build --rm --no-cache -t "$IMAGE_NAME:$TARGET" . #>/dev/null 2>&1 fi echo "Done."