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."