sk_fems_apigw commit

This commit is contained in:
unknown
2025-07-12 15:03:31 +09:00
parent b6841161e1
commit c7414f013c
24 changed files with 1739 additions and 0 deletions

49
.classpath Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

37
.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
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/
### Mac File ###
./DS_Store
*.log

42
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,42 @@
services:
- docker:19.03.7-dind
stages:
- build_jar
- build_docker_image
build:
image: maven:3.6.3-jdk-11-slim
stage: build_jar
script:
# maven build
- echo "=====maven build start====="
- mvn clean install
- echo "=====maven build end====="
tags:
- test
docker-build:
variables:
# do not clone again
GIT_STRATEGY: none
stage: build_docker_image
script:
# make docker image and push to local docker
- echo "=====make docker image and push to local docker start====="
- sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- sudo docker build -t $CI_REGISTRY/root/registry/skfems/apigw .
- echo "=====make docker image and push to local docker end====="
# push local image to local registry
- echo "=====push local image to local registry start====="
- sudo docker push $CI_REGISTRY/root/registry/skfems/apigw
- sudo docker rmi $CI_REGISTRY/root/registry/skfems/apigw
- echo "=====push local image to local registry end====="
# comm.base 모듈 분리 배포
- echo "=====node build_docker_image comm.base module start====="
- sudo docker build -f Dockerfile.keti -t $CI_REGISTRY/root/registry/skfems/apigw_keti .
- sudo docker push $CI_REGISTRY/root/registry/skfems/apigw_keti
- sudo docker rmi $CI_REGISTRY/root/registry/skfems/apigw_keti
- echo "=====node build_docker_image comm module end====="
tags:
- test

117
.mvn/wrapper/MavenWrapperDownloader.java vendored Normal file
View File

@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* 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
*
* 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.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

BIN
.mvn/wrapper/maven-wrapper.jar vendored Normal file

Binary file not shown.

2
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@ -0,0 +1,2 @@
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/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,4 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=target\\generated-sources\\annotations
org.eclipse.jdt.apt.genTestSrcDir=target\\generated-test-sources\\test-annotations

View File

@ -0,0 +1,17 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.processAnnotations=enabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1

13
Dockerfile Normal file
View File

@ -0,0 +1,13 @@
# Build stage
FROM maven:3.6.0-jdk-11-slim AS build
COPY src /app/src
COPY pom.xml /app
RUN mvn -f /app/pom.xml clean install -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
# Package stage
FROM openjdk:11-jre-slim
COPY --from=build /app/target/*.jar /usr/local/lib/apigw.jar
EXPOSE 9999
ENV SPRING_PROFILES_ACTIVE cloud_kube
ENV SYS_SETTING ""
ENTRYPOINT ["java","-jar","/usr/local/lib/apigw.jar", "--spring.profiles.active=${SPRING_PROFILES_ACTIVE}", "${SYS_SETTING}"]

13
Dockerfile.keti Normal file
View File

@ -0,0 +1,13 @@
# Build stage
FROM maven:3.6.0-jdk-11-slim AS build
COPY src /app/src
COPY pom.xml /app
RUN mvn -f /app/pom.xml clean install -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
# Package stage
FROM openjdk:11-jre-slim
COPY --from=build /app/target/*.jar /usr/local/lib/apigw.jar
EXPOSE 9999
ENV SPRING_PROFILES_ACTIVE docker
ENV SYS_SETTING ""
ENTRYPOINT ["java","-jar","/usr/local/lib/apigw.jar", "--spring.profiles.active=${SPRING_PROFILES_ACTIVE}", "${SYS_SETTING}"]

310
mvnw vendored Normal file
View File

@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# 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
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# 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`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
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" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
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
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
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"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
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.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
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" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

182
mvnw.cmd vendored Normal file
View File

@ -0,0 +1,182 @@
@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 "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\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/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "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%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.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 "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\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%
exit /B %ERROR_CODE%

118
pom.xml Normal file
View File

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lsitc.fems</groupId>
<artifactId>SpringCloudGateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringCloudGateway</name>
<description>SpringCloudGateway</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.2</version>
</dependency>
<!-- 메트릭을 Endpoint로 노출 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Micrometer core dependecy -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<!-- Micrometer Prometheus registry -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,32 @@
package com.lsitc.fems.SpringCloudGateway;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.core.env.Environment;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class PassCorsRoutePredicateHandlerMapping extends RoutePredicateHandlerMapping {
private static final Logger logger = LoggerFactory.getLogger(PassCorsRoutePredicateHandlerMapping.class);
public PassCorsRoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
super(webHandler, routeLocator, globalCorsProperties, environment);
}
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {
logger.info("[PassCorsRoutePredicateHandlerMapping] getHandler");
return getHandlerInternal(exchange).map(handler -> {
logger.info(exchange.getLogPrefix() + "Mapped to " + handler);
// CORS 체크 로직 제거
return handler;
});
}
}

View File

@ -0,0 +1,28 @@
package com.lsitc.fems.SpringCloudGateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
@SpringBootApplication
public class SpringCloudGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudGatewayApplication.class, args);
}
@Bean
@Primary
public RoutePredicateHandlerMapping passCorsRoutePredicateHandlerMapping(
FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
return new PassCorsRoutePredicateHandlerMapping(webHandler, routeLocator,
globalCorsProperties, environment);
}
}

View File

@ -0,0 +1,229 @@
/*
* 상기 프로그램에 대한 저작권을 포함한 지적재산권은 LS ITC에 있으며,
* LS와 명시적으로 허용하지 않은 사용, 복사, 변경, 제3자에의 공개, 배포는 엄격히 금지되며,
* LS의 지적재산권 침해에 해당됩니다.
* (Copyright ⓒ 2021 LS ITC. All Rights Reserved| Confidential)
*
* You are strictly prohibited to copy, disclose, distribute, modify, or use
* this program in part or as a whole without the prior written consent of
* LS. LS owns the intellectual property rights in
* and to this program.
* (Copyright ⓒ 2021 LS. All Rights Reserved| Confidential)
* Created : 2021.04.06
*/
package com.lsitc.fems.SpringCloudGateway.filter;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@SuppressWarnings("rawtypes")
@Component
public class AuthFilter extends AbstractGatewayFilterFactory<Map> {
private Logger logger = LoggerFactory.getLogger(AuthFilter.class);
private String authServiceUrl = "";
private String loginUrl = "";
private String cookieId = "";
private final WebClient webClient = WebClient.create();
public AuthFilter() {
super(Map.class);
}
@Override
public GatewayFilter apply(Map config) {
authServiceUrl = config.get("authAPI").toString();
cookieId = config.get("cookieId").toString();
loginUrl = config.get("loginUrl").toString();
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
// 로그인 및 권한 Check 호출
Mono<ClientResponse> authServiceResponse = callAuthService(request);
// 후처리
Mono<Void> middleService = authServiceResponse.flatMap(r -> processAuthResponse(exchange, chain, request, r));
return middleService.then();
};
}
/**
* @methodName : resolveBodyFromRequest
* @date : 2021.05.06
* @desc : requestBody를 String으로 변환하여 반환한다.
* @param serverHttpRequest
* @return
*/
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
// Get the request body
Flux<DataBuffer> body = serverHttpRequest.getBody();
AtomicReference<String> bodyRef = new AtomicReference<>();
body.subscribe(buffer -> {
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
DataBufferUtils.release(buffer);
bodyRef.set(charBuffer.toString());
});
// Get request body
return bodyRef.get();
}
/**
*
* @methodName : callAuthService
* @date : 2021.04.15
* @desc : 로그인 및 권한 check API 호출
* @param inputRequest
* @return
*/
private Mono<ClientResponse> callAuthService(ServerHttpRequest inputRequest) {
logger.info("requestURI : {}", inputRequest.getPath());
Map<String, String> params = new HashMap<>();
params.put("requestURI", inputRequest.getPath().toString());
if( inputRequest.getMethod().matches("POST") ) {
//POST는 header에서
List<String> menuId = inputRequest.getHeaders().get("X-Fems-MenuId");
logger.info("X-Fems-MenuId : {}", menuId);
params.put("menuId", menuId.get(0));
// String requestBodyStr = resolveBodyFromRequest(inputRequest);
// ObjectMapper mapper = new ObjectMapper();
// JsonNode actualObj;
// try {
// //requestBody
// actualObj = mapper.readTree(requestBodyStr);
// //menuId
// params.put("menuId", actualObj.get("params").get("menuId") != null ? actualObj.get("params").get("menuId").asText() : "2");
// } catch (Exception e) {
// }
} else {
//POST는 queryString에서(e.g. menu)
params.put("menuId", inputRequest.getQueryParams().getFirst("$menuId"));
}
System.out.println("getHeaders" + inputRequest.getHeaders());
System.out.println("authServiceUrl : " + authServiceUrl);
System.out.println("cookieId : " + cookieId);
System.out.println("getCookies : " + inputRequest.getCookies().toString());
System.out.println("getFirst(cookieId) : " + inputRequest.getCookies().getFirst(cookieId));
WebClient.RequestBodySpec request = webClient.method(HttpMethod.POST).uri(authServiceUrl)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
.cookie(cookieId,
inputRequest.getCookies().getFirst(cookieId) != null
? inputRequest.getCookies().getFirst(cookieId).getValue()
: "");
request.bodyValue(params);
return request.exchange();
}
/**
*
* @methodName : processMiddleResponse
* @date : 2021.04.15
* @desc :
* @param exchange
* @param chain
* @param request
* @param middleServiceResponse
* @return
*/
private Mono<Void> processAuthResponse(ServerWebExchange exchange, GatewayFilterChain chain,
ServerHttpRequest request, ClientResponse authServiceResponse) {
if (authServiceResponse.statusCode().is2xxSuccessful()) {
// 로그인 및 권한 체크 결과 정상이면 새로 발급된 쿠키를 담아준다.
ServerHttpRequest modifiedRequest = request.mutate().headers((httpHeaders) -> {
httpHeaders.set("Cookie",
authServiceResponse.cookies().get(cookieId) != null
? authServiceResponse.cookies().get(cookieId).get(0).toString()
: "");
}).build();
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
ResponseCookie cookie = authServiceResponse.cookies().get(cookieId).get(0);
exchange.getResponse().addCookie(cookie);
System.out.println("exchange.getResponse is2xxSuccessful" + exchange.getResponse());
// authServiceResponse.bodyToMono(Map.class).subscribe(m -> {
//// logger.info("retnCd :: {}", m.get("retnCd"));
// });
return chain.filter(modifiedExchange);
} else {
System.out.println("exchange.getResponse else is2xxSuccessful" + exchange.getResponse().getHeaders());
System.out.println("exchange.getResponse else is2xxSuccessful" + exchange.getResponse().getCookies());
if (exchange.getRequest().getHeaders().getAccept().contains(MediaType.APPLICATION_JSON)) {
ObjectMapper objectMapper = new ObjectMapper();
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
exchange.getResponse().setStatusCode(HttpStatus.OK);
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
DataBuffer dataBuffer = null;
try {
dataBuffer = bufferFactory
.wrap(objectMapper.writeValueAsBytes(new HttpError("-1", "문제가 발생하였습니다. 관리자에게 문의하세요.")));
} catch (JsonProcessingException e) {
dataBuffer = bufferFactory.wrap("".getBytes());
}
return exchange.getResponse().writeWith(Mono.just(dataBuffer));
} else {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.MOVED_TEMPORARILY);
try {
response.getHeaders().setLocation(new URI(loginUrl));
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
}
return Mono.empty();
}
}
}
public class HttpError {
private String rtnCd;
private String message;
HttpError(String rtnCd, String message) {
this.rtnCd = rtnCd;
this.message = message;
}
public String getMessage() {
return message;
}
public String getRtnCd() {
return rtnCd;
}
}
}

View File

@ -0,0 +1,58 @@
/*
* 상기 프로그램에 대한 저작권을 포함한 지적재산권은 LS ITC에 있으며,
* LS와 명시적으로 허용하지 않은 사용, 복사, 변경, 제3자에의 공개, 배포는 엄격히 금지되며,
* LS의 지적재산권 침해에 해당됩니다.
* (Copyright ⓒ 2021 LS ITC. All Rights Reserved| Confidential)
*
* You are strictly prohibited to copy, disclose, distribute, modify, or use
* this program in part or as a whole without the prior written consent of
* LS. LS owns the intellectual property rights in
* and to this program.
* (Copyright ⓒ 2021 LS. All Rights Reserved| Confidential)
* Created : 2021.05.06
*/
package com.lsitc.fems.SpringCloudGateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Component
public class CacheRequestBodyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (exchange.getRequest().getHeaders().getContentType() == null || exchange.getRequest().getMethod().matches("GET")) {
return chain.filter(exchange);
} else {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
DataBufferUtils.retain(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux
.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
return chain.filter(exchange.mutate().request(mutatedRequest).build());
});
}
}
@Override
public int getOrder() {
return 0;
}
}

View File

@ -0,0 +1,157 @@
package com.lsitc.fems.SpringCloudGateway.filter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Mono;
@SuppressWarnings("rawtypes")
@Component
public class MenuLogFilter extends AbstractGatewayFilterFactory<Map> {
private Logger logger = LoggerFactory.getLogger(MenuLogFilter.class);
private String menuLogServiceUrl = "";
private String loginUrl = "";
private String cookieId = "";
private final WebClient webClient = WebClient.create();
public MenuLogFilter() {
super(Map.class);
}
@Override
public GatewayFilter apply(Map config) {
menuLogServiceUrl = config.get("menuLogAPI").toString();
cookieId = config.get("cookieId").toString();
loginUrl = config.get("loginUrl").toString();
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
// 로그인 및 권한 Check 호출
Mono<ClientResponse> menuLogServiceResponse = callMenuLogService(request);
// 후처리
Mono<Void> middleService = menuLogServiceResponse.flatMap(r -> processMenuLogResponse(exchange, chain, request, r));
return middleService.then();
};
}
private Mono<ClientResponse> callMenuLogService(ServerHttpRequest inputRequest) {
logger.info("callMenuLogService : {}", inputRequest.getPath());
Map<String, String> params = new HashMap<>();
params.put("requestURI", inputRequest.getPath().toString());
if( inputRequest.getMethod().matches("POST") ) {
//POST는 header에서
List<String> menuId = inputRequest.getHeaders().get("X-Fems-MenuId");
logger.info("X-Fems-MenuId : {}", menuId);
params.put("menuId", menuId.get(0));
} else {
//POST는 queryString에서(e.g. menu)
String menuId = inputRequest.getQueryParams().getFirst("$menuId");
params.put("menuId", menuId == null?"0":menuId);
}
WebClient.RequestBodySpec request = webClient.method(HttpMethod.POST).uri(menuLogServiceUrl)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
.cookie(cookieId,
inputRequest.getCookies().getFirst(cookieId) != null
? inputRequest.getCookies().getFirst(cookieId).getValue()
: "");
request.bodyValue(params);
return request.exchange();
}
private Mono<Void> processMenuLogResponse(ServerWebExchange exchange, GatewayFilterChain chain,
ServerHttpRequest request, ClientResponse authServiceResponse) {
if (authServiceResponse.statusCode().is2xxSuccessful()) {
// 로그인 및 권한 체크 결과 정상이면 새로 발급된 쿠키를 담아준다.
ServerHttpRequest modifiedRequest = request.mutate().headers((httpHeaders) -> {
httpHeaders.set("Cookie",
authServiceResponse.cookies().get(cookieId) != null
? authServiceResponse.cookies().get(cookieId).get(0).toString()
: "");
}).build();
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
ResponseCookie cookie = authServiceResponse.cookies().get(cookieId).get(0);
exchange.getResponse().addCookie(cookie);
// authServiceResponse.bodyToMono(Map.class).subscribe(m -> {
//// logger.info("retnCd :: {}", m.get("retnCd"));
// });
return chain.filter(modifiedExchange);
} else {
if (exchange.getRequest().getHeaders().getAccept().contains(MediaType.APPLICATION_JSON)) {
ObjectMapper objectMapper = new ObjectMapper();
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
exchange.getResponse().setStatusCode(HttpStatus.OK);
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
DataBuffer dataBuffer = null;
try {
dataBuffer = bufferFactory
.wrap(objectMapper.writeValueAsBytes(new HttpError("-1", "문제가 발생하였습니다. 관리자에게 문의하세요.")));
} catch (JsonProcessingException e) {
dataBuffer = bufferFactory.wrap("".getBytes());
}
return exchange.getResponse().writeWith(Mono.just(dataBuffer));
} else {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.MOVED_TEMPORARILY);
try {
response.getHeaders().setLocation(new URI(loginUrl));
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
}
return Mono.empty();
}
}
}
public class HttpError {
private String rtnCd;
private String message;
HttpError(String rtnCd, String message) {
this.rtnCd = rtnCd;
this.message = message;
}
public String getMessage() {
return message;
}
public String getRtnCd() {
return rtnCd;
}
}
}

View File

@ -0,0 +1,241 @@
# 공통
spring:
application:
#업무명
name: apiGw
serverip: localhost
profiles:
#프로파일(local:로컬환경, dev:개발환경(추가환경개발), docker:운영 택1)
active: local
#로깅관련
logging:
loginLogEnable: true
menuCnctLogEnable: true
level:
root: DEBUG
#logging
config: classpath:logback_spring.xml
file:
path: logs
max-history: 30
max-size: 100MB
---
##############
####local#####
##############
#AuthFilter정의
AuthFilter: &AuthFilter
- name: AuthFilter
args:
authAPI: http://localhost:8080/isValidToken
cookieId: FEMS_SESSION
loginUrl: /login
MenuLogFilter: &MenuLogFilter
- name: MenuLogFilter
args:
menuLogAPI: http://localhost:8080/menuLogCont
cookieId: FEMS_SESSION
loginUrl: /login
#MenuLogFilter: &MenuLogFilter
# - name: MenuLogFilter
# args:
# menuLogAPI: http://localhost:9999/menuLogCont
# cookieId: FEMS_SESSION
# loginUrl: http://localhost:9999/login
spring:
profiles: local
main:
allow-bean-definition-overriding: true
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
#timeout관련 설정
httpclient:
connect-timeout: 300000 # 30초
response-timeout: 300s # 30초, 글로벌 설정시 seconds
pool:
max-idle-time: 300000 # 5분간 휴상태이면 회수 처리
#routing관련 설정
routes:
# withoutAuth
- id: withOutAuth #id
uri: http://localhost:8080/comm #forward url
predicates:
- Path= /loginChk, /logout, /isValidToken, /menuLogCont, /sso, /comm/SystemLogReadCtr/saveMenuCnctLog, /loginProc #, /login
# withOutEms
- id: withOutEms
uri: http://localhost:8082/
predicates:
- Path=/ems/effc/MdlDataSetCtr/selectMdlOpen
# vuePage
- id: vuePage
uri: http://localhost:3000/
filters:
- <<: *MenuLogFilter
predicates:
#라우팅할 path
- Path=/ems/**/*Page, /comm/**/*Page
# vue.js
- id: vue #id
uri: http://localhost:3000/ #forward url
predicates:
#라우팅할 path
- Path=/_nuxt/comm/**, /__webpack_hmr/**, /_loading/**, /favicon.ico, /login, /ems/*Page, /comm/*Page, /iframe/**, /
# vue sample
- id: vueSample #id
uri: http://localhost:3010/ #forward url
predicates:
#라우팅할 path
- Path=/_nuxt/sample/**, /sample/*Page
# comm
- id: comm #id
uri: http://localhost:8080 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/comm/** #, /
# ems
- id: ems #id
uri: http://localhost:8082 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/ems/base/**, /ems/api/** ,/ems/bala/**, /ems/effc/**
# ems_fopm
- id: ems_fopm #id
uri: http://localhost:8084 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/fopm/**
# drp
- id: drp #id
uri: http://localhost:8086 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/ems/drp/**
# cmms
- id: cmms #id
uri: http://localhost:8089 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/cmms/**
# sample
- id: sample #id
uri: http://localhost:8090 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/sample/**
management:
endpoints:
web:
exposure:
include: "gateway"
endpoint:
gateway:
enabled: true
server:
port: 9999
---
###############################
#### Cloud(Kube) #####
###############################
AuthFilter: &AuthFilter
- name: AuthFilter
args:
authAPI: http://skfems-comm:8080/isValidToken
cookieId: FEMS_SESSION
loginUrl: /login
MenuLogFilter: &MenuLogFilter
- name: MenuLogFilter
args:
menuLogAPI: http://skfems-comm:8080/menuLogCont
cookieId: FEMS_SESSION
loginUrl: /login
spring:
profiles: cloud_kube
main:
allow-bean-definition-overriding: true
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
#timeout관련 설정
httpclient:
connect-timeout: 300000 # 30초
response-timeout: 300s # 30초, 글로벌 설정시 seconds
pool:
max-idle-time: 300000 # 5분간 휴상태이면 회수 처리
#routing관련 설정
routes:
# withoutAuth
- id: withOutAuth #id
uri: http://skfems-comm:8080/ #forward url
predicates:
- Path= /loginChk, /logout, /isValidToken, /menuLogCont, /comm/base/SystemLogReadCtr/saveMenuCnctLog, /loginProc #, /login
# withOutEms
- id: withOutEms
uri: http://skfems-ems:8082/
predicates:
- Path=/ems/effc/MdlDataSetCtr/selectMdlOpen
# vueCommAuthPage
- id: vueCommAuthPage
uri: http://skfems-ui:3000/
filters:
- <<: *MenuLogFilter
predicates:
#라우팅할 path
- Path=/comm/**/*Page, /ems/**/*Page
# vue.js
- id: vue #id
uri: http://skfems-ui:3000/ #forward url
predicates:
#라우팅할 path
- Path=/_nuxt/comm/**, /__webpack_hmr/**, /_loading/**, /favicon.ico, /login, /iframe/**, /
# comm
- id: comm #id
uri: http://skfems-comm:8080 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/comm/**
# ems
- id: ems #id
uri: http://skfems-ems:8082 #forward url
filters:
- <<: *AuthFilter
predicates:
#라우팅할 path
- Path=/ems/**
# webHmi
- id: webHmi #id
uri: http://skfems-fuxa:1881 #forward url
predicates:
#라우팅할 path
- Path=/webHmi/**
management:
endpoints:
web:
exposure:
include: "gateway"
endpoint:
gateway:
enabled: true
server:
port: 9999

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 60초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="60 seconds">
<!--springProfile 태그를 사용하면 logback 설정파일에서 복수개의 프로파일을 설정할 수 있다. -->
<springProperty scope="context" name="LOG_LEVEL" source="logging.level.root" />
<!-- log file path -->
<springProperty scope="context" name="LOG_PATH" source="logging.file.path"/>
<!-- log file name -->
<springProperty scope="context" name="LOG_FILE_NAME" source="spring.application.name"/>
<!-- log file size -->
<springProperty scope="context" name="LOG_MAX-SIZE" source="logging.file.max-size"/>
<!-- log history -->
<springProperty scope="context" name="LOG_MAX_HISTORY" source="logging.file.max-history"/>
<!-- pattern -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%-6level] [%logger{0}:%line] - %msg%n" />
<!-- Console Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- File Appender -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 파일경로 설정 -->
<file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
<!-- 출력패턴 설정 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
<fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 파일당 최고 용량 kb, mb, gb -->
<maxFileSize>${LOG_MAX-SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 -->
<maxHistory>${LOG_MAX_HISTORY}</maxHistory>
<!--<MinIndex>1</MinIndex> <MaxIndex>10</MaxIndex> -->
</rollingPolicy>
</appender>
<root level="${LOG_LEVEL}">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
<!-- log4jdbc 옵션 설정 -->
<logger name="jdbc" level="OFF" />
<!-- 커넥션 open close 이벤트를 로그로 남긴다. -->
<logger name="jdbc.connection" level="OFF" />
<!-- SQL문만을 로그로 남기며, PreparedStatement일 경우 관련된 argument 값으로 대체된 SQL문이 보여진다. -->
<logger name="jdbc.sqlonly" level="OFF" />
<!-- SQL문과 해당 SQL을 실행시키는데 수행된 시간 정보(milliseconds)를 포함한다. -->
<logger name="jdbc.sqltiming" level="DEBUG" />
<!-- ResultSet을 제외한 모든 JDBC 호출 정보를 로그로 남긴다. 많은 양의 로그가 생성되므로 특별히 JDBC 문제를 추적해야 할 필요가 있는 경우를 제외하고는 사용을 권장하지 않는다. -->
<logger name="jdbc.audit" level="OFF" />
<!-- ResultSet을 포함한 모든 JDBC 호출 정보를 로그로 남기므로 매우 방대한 양의 로그가 생성된다. -->
<logger name="jdbc.resultset" level="OFF" />
<!-- SQL 결과 조회된 데이터의 table을 로그로 남긴다. -->
<logger name="jdbc.resultsettable" level="OFF" />
</configuration>

View File

@ -0,0 +1,13 @@
package com.lsitc.fems.SpringCloudGateway;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringCloudGatewayApplicationTests {
@Test
void contextLoads() {
}
}