Skip to content

Commit 8ad3d19

Browse files
committed
0.0.3
1 parent aaf4321 commit 8ad3d19

37 files changed

Lines changed: 2670 additions & 658 deletions

README.md

23.2 KB

Шаблон HTTP сервера на Golang

Представленный ниже шаблон HTTP сервера был подготовлен для передачи знаний внутри нашей команды после реализации одного изнескольких проектов на Go. Шаблон не претендует на глобальную универсальность, но, возможно, отдельные его части могут быть полезны остальным.

Шаблон включает:

Шаблон сервера включает:

  • Передача параметров для запуска HTTP сервера через командную строку
  • Настрой уровней логирования
  • Настройка параметров HTTP сервера и связанных сервисов через конфигурационный файл
  • Настройка параметров TLS
  • Создание роутера и регистрация HTTP обработчиков и prof-обработчиков
  • Запуск HTTP сервера с ожиданием возврата в канал ошибок
  • Использование контекста для корректной остановки сервера и связанных сервисов
  • Кастомная обработка ошибок
  • Логирования HTTP запросов (тело и заголовок, входящих и исходящих запросов и ответов)
  • Использование Basic аутентификации
  • Использование MS AD аутентификации
  • Использование JSON Web Token
  • Простая сборка с внедрением номер версии, даты сбори и номера commit

Предиыстория

В ходе внедрения 1С:ERP у одного крупного заказчика, появилась интересная задача - интеграция 1С с корпоративной шиной IBM MQ. Ключевыми требованиями в части взаимодействтия с IBM MQ были:

Архитектура REST адаптера 1С <-> IBM MQ

Архитектура адаптера REST API к IBM MQ укрупненно показана на следующем рисунке.
В настоящей статье речь пойдет только об одной компоненте - HTTP сервере.

Архитектура адаптера REST API к IBM MQ укрупненно показана на следующем рисунке.

REST_IBMMQ

Подход к сСозданию, запуску и остановкеа сервера

На следующем рисунке показана упрощенная UML диаграмма последовательности запуска и остановки сервера.

Для координации создания, запуска и остановки сервера вводится понятие daemon. В его задачи входит:

  • считывание конфигурационного файла
  • настрока концигурацияи сервисов
  • создание контекста context.Context и каналов ошибок для обратной связи с сервисами
  • создание зависимых сервисов
  • корректный запуск сервисов
  • ожидание системных прерываний и/или ошибок от сервисов
  • корректная остановка сервисов

Создание daemon и сервисов

В общем случае, сервисы создаются и настраиваются при создании daemon. Сервисы могут быть взаимосвязанными - это определяется спецификой решения. Если есть ошибки при создании отдельных сервисах, то daemon не создается.
Для каждого сервиса, который должен работать в фоне в daemon создается отдельный канал ошибок.

// создаем новый контекст с отменой и отсрочкой ShutdownTimeout
cancelCtx, cancel := context.WithTimeout(s.ctx, time.Duration(s.cfg.ShutdownTimeout*int(time.Second)))
defer cancel()

// ожидаем закрытия активных подключений в течении ShutdownTimeout
if err := s.httpServer.Shutdown(cancelCtx); err != nil {
    return err
}
s.httpService.Shutdown() // Останавливаем служебные сервисы

Подход к обработке ошибок

Обработка ошибок

Структура ошибки

Один из наиболее удачных пакетов для обработки ошибок github.com/pkg/errors.
Первоначально использовал его, но со временем стало не хватать структурности ошибки, поэтому перешел на простой кастомный пакет ().

Для упрощения отладки, использовался следующий подход для логирования ошибок:

Структура для хранения ошибки:

type Error struct {
	ID       uint64 // уникальный номер ошибки
	Code     string // код ошибки
	Msg      string // текст ошибки
	Caller   string // файл, строка и наименование метода в месте создания ошибки
	Args     string // строка аргументов
	CauseErr error  // ошибка - причина
	CauseMsg string // текст ошибки - причины
	Trace    string // стек вызова в месте создания ошибки
}

Мне удобно работать с типизированными ошибками, поэтому код ошибки выделен отдельным атрибутом. В адаптере IBM MQ, использовался простой 4 символьный числовой код. Например, ошибки начинающиеся с "8ххх" относились к HTTP, с "7ххх" - к IBM MQ.

Caller - место регистрации ошибки, если нет необходимости выводить полный стек. Пример вывода:

httpserver.go:[209] - (*Server).Run()

Вычисляется функцией

func caller(depth int) string {
	pc := make([]uintptr, 15)
	n := runtime.Callers(depth+1, pc)
	frame, _ := runtime.CallersFrames(pc[:n]).Next()
	idxFile := strings.LastIndexByte(frame.File, '/')
	idx := strings.LastIndexByte(frame.Function, '/')
	idxName := strings.IndexByte(frame.Function[idx+1:], '.') + idx + 1

	return frame.File[idxFile+1:] + ":[" + strconv.Itoa(frame.Line) + "] - " + frame.Function[idxName+1:] + "()"
}

Args - отдельная строка аргументов, которые можно добавить к сообщению при создании ошибок. Используется для целей отладки.

CauseErr и CauseMsg - исходная ошибка и сообщение. Используется, если оборачиваем чужую ошибку в свою структуру.

Trace - стандартный трейс стека. Для его получения использовал своеобразный подход. При регистрации ошибки создавал пустую ошибку из пакета github.com/pkg/errors и печатал ее с ключом '%+v'. В этом режиме она выводит стек.

fmt.Sprintf("'%+v'", pkgerr.New("")

Форматирование ошибок

Для соответствия интерфейсу Error используется вывод в сокращенном формате.

func (e *Error) Error() string {
	mes := fmt.Sprintf("ID=[%v], code=[%s], mes=[%s]", e.ID, e.Code, e.Msg)
	if e.Args != "" {
		mes = fmt.Sprintf("%s, args=[%s]", mes, e.Args)
	}
	if e.CauseMsg != "" {
		mes = fmt.Sprintf("%s, causemes=[%s]", mes, e.CauseMsg)
	}
	return mes
}

Пример вывода в сокращенном формате

ID=[1], code=[8004], mes=[Error message], args=['arg1', 'arg2', 'arg3']

Для форматированного вывода используются ключи

// %s    print the error code, message, arguments, and cause message.
// %v    in addition to %s, print caller
// %+v   extended format. Each Frame of the error's StackTrace will be printed in detail.
func (e *Error) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		fmt.Fprint(s, e.Error())
		fmt.Fprintf(s, ", caller=[%s]", e.Caller)
		if s.Flag('+') {
			fmt.Fprintf(s, ", trace=%s", e.Trace)
			return
		}
	case 's':
		fmt.Fprint(s, e.Error())
	case 'q':
		fmt.Fprint(s, e.Error())
	}
}

Пример вывода с ключом '%+v'

ID=[1], code=[8004], mes=[Error message], args=['arg1', 'arg2', 'arg3'], caller=[handler_echo.go:[31] - (*Service).EchoHandler.func1()], trace='
github.com/romapres2010/httpserver/error.New
        D:/golang/src/github.com/romapres2010/httpserver/error/error.go:72
github.com/romapres2010/httpserver/httpserver/httpservice.(*Service).EchoHandler.func1
        D:/golang/src/github.com/romapres2010/httpserver/httpserver/httpservice/handler_echo.go:31
        ...

Предложенный формат вывода не полностью соответствует подходу структурированного логирования, это сделано специально для более удобного чтения лога в ходе отладки. Если нужнем боле строгий формат - достаточно поправить в одном месте метод Format.

Регистрация ошибок

Используются два метода для регистрации ошибок:

  • Создание новой ошибки - New(code string, msg string, args ...interface{}) error
  • Оборачивание существующей ошибки - WithCause(code string, msg string, causeErr error, args ...interface{}) error

Дополнительные аргументы можно либо встроить в сообщение ошибки, либо передать дополнительными параметрами в args ...interface{}.

Все ошибки от сторонних и стандартных пакетов оборачиваются в кастомную ошибку в месте возникновения. Исходная ошибка вкладывается внутрь кастомной.

myerr = myerror.WithCause("8001", "Failed to read HTTP body: reqID", err, reqID)

Логирование и обработка ошибок

Использовался следующий подход:

  • в точке возникновения, ошибка логируется на уровне INFO без trace. В этот момент, ещеобычно, не известно, является ли это ошибкой, или она будет обработана на уровне выше
  • при передаче ошибок на уровень вверх она повторно не оборачивается в WithCause()
  • в точке обработки ошибки логируесттся результат обработки на уровне INFO. Ошибка перестает быть ошибкой.
  • если ошибка дошла необработанной до самого верхнего уровня, значит это действительно ошибка и она логируется на уровне ERROR с максимальной детальностью, включая trace.

Подход к логированию

Для логирования использовался пакет github.com/hashicorp/logutils.

Из рекомендованного списка уровней логирования RFC 5424 — The Syslog Protocol, оставил следующие:

Например, при ошибке чтения тела HTTP запроса:

requestBuf, err := ioutil.ReadAll(r.Body)
if err != nil {
    myerr = myerror.WithCause("8001", "Failed to read HTTP body: reqID", err, reqID)
    mylog.PrintfErrorInfo(myerr) // стандартное сокращенное логирование ошибки
    s.processError(myerr, w, http.StatusInternalServerError, reqID) // расширенное логирование ошибки в HTTP response
    return myerr
}

Методом processError дополнительно ошибка может логироваться в заголовок HTTP ответа и/или тело ответа. Необходимость такого логирования настраивается в конфигурационном файле сервера - параметр HTTPErrLog, или динамически вызовом POST на /httperrlog.

POST /httperrlog HTTP/1.1
Host: 127.0.0.1:3000
HTTP-Err-Log: HEADER | BODY

При логировании в header ответа нужно исключить все управляющие символы

// carriage return (CR, ASCII 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII 0x0)
headerReplacer := strings.NewReplacer("\x0a", " ", "\x0d", " ", "\x00", " ")

w.Header().Set("Err-Trace", headerReplacer.Replace(myerr.Trace))

Логирование

Для управления уровнями логирования использовался пакет github.com/hashicorp/logutils. Из рекомендованного списка уровней логирования RFC 5424 — The Syslog Protocol, оставил только 3:

  • debug — подробная информация для отладки
  • info — полезные события, например, запуск/останов сервиса
  • error — ошибки исполнения, требующие вмешательства

Ссылка на полезную статью от Dave Cheney Let’s talk about logging.

Кастомной пакет логирования получился крайне простым - всего 100 строк

Ссылка на полезную статью от Dave Cheney Let’s talk about logging. Если предложенный вариант логирования покажется слишком простым - то рекомендую посмотреть в сторону A simple logging interface for Go.

Структура пакетов

Основные пакеты сервера:

  • main - обрабатывает параметры командной строки, создает демон, запускет его и ожидает завершения.
  • daemon - создает и связывает все сервисы, запускает и корректно их останавливает.
  • httpserver - собственно HTTP сервер. Включает в себя: листенер, роутер, HTTP сервер, набор обработчиков.
  • httpservice - набор обработчиков HTTP запросов.
  • httplog - логирование входящих и исходящих запросов и ответов, включая заголовок и тело.

Куда логируем

Все логирование идет через стандартный пакет "log". Но для него подменяется вывод на кастомный логер github.com/hashicorp/logutils.

// logFilter represent a custom logger seting
var logFilter = &logutils.LevelFilter{
	Levels:   []logutils.LogLevel{"DEBUG", "INFO", "ERROR"},
	MinLevel: logutils.LogLevel("INFO"), // initial setting
	Writer:   os.Stderr,                 // initial setting
}

// InitLogger init custom logger
func InitLogger(wrt io.Writer) {
	logFilter.Writer = wrt   // custom logger
	log.SetOutput(logFilter) // set std logger to our custom
}

При необходимости, можно параллельно логировать в файл, для этого на уровне main создается лог файл и устанавливается MultiWriter

// настраиваем параллельное логирование в файл
if logFileFlag != "" {
    // добавляем в имя лог файла дату и время
    logFileFlag = strings.Replace(logFileFlag, "%s", time.Now().Format("2006_01_02_150405"), 1)

    // открываем лог файл на запись в режиме APPEND
    logFile, err := os.OpenFile(logFileFlag, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        myerr := myerror.WithCause("6020", "Error open log file: Filename", err, logFileFlag)
        mylog.PrintfErrorMsg(fmt.Sprintf("%+v", myerr))
        return myerr
    }
    if logFile != nil {
        defer logFile.Close()
    }

    wrt := io.MultiWriter(os.Stderr, logFile) // параллельно пишем в os.Stderr и файл

    mylog.InitLogger(wrt) // переопределяем стандратный логер на кастомный
} else {
    mylog.InitLogger(os.Stderr)
}

Формат логирования

Логирование в режиме INFO и DEBUG сделано немного более дружественным чем логирование ошибок.

2020/03/10 17:56:39 [INFO] - httpserver.go:[61] - New() - Creating new HTTP server
2020/03/10 17:56:39 [INFO] - httpserver.go:[141] - New() - Created new TCP listener: network = 'tcp', address ['127.0.0.1:3000']
2020/03/10 17:56:39 [INFO] - httpserver.go:[155] - New() - Handler is registered: Path, Method ['/echo', 'POST']
2020/03/10 17:56:39 [INFO] - httpserver.go:[155] - New() - Handler is registered: Path, Method ['/signin', 'POST']
2020/03/10 17:56:39 [INFO] - httpserver.go:[155] - New() - Handler is registered: Path, Method ['/refresh', 'POST']
2020/03/10 17:56:39 [INFO] - httpserver.go:[179] - New() - HTTP server is created
2020/03/10 17:56:39 [INFO] - daemon.go:[121] - New() - New daemon is created
2020/03/10 17:56:39 [INFO] - daemon.go:[128] - (*Daemon).Run() - Starting daemon
2020/03/10 17:56:39 [INFO] - daemon.go:[133] - (*Daemon).Run() - Daemon is running. For exit <CTRL-c>
2020/03/10 17:56:39 [INFO] - httpserver.go:[209] - (*Server).Run() - Starting HTTP server
2020/03/10 17:57:22 [INFO] - daemon.go:[142] - (*Daemon).Run() - Exiting, got signal ['interrupt']
2020/03/10 17:57:22 [INFO] - daemon.go:[155] - (*Daemon).Shutdown() - Shutting down daemon
2020/03/10 17:57:22 [INFO] - httpserver.go:[215] - (*Server).Shutdown() - Waiting for shutdown HTTP Server: sec ['30']
2020/03/10 17:57:22 [INFO] - httpserver.go:[231] - (*Server).Shutdown() - HTTP Server shutdown successfuly
2020/03/10 17:57:22 [INFO] - daemon.go:[167] - (*Daemon).Shutdown() - Daemon is shutdown
2020/03/10 17:57:22 [INFO] - main.go:[163] - main.func1() - Server is shutdown

В режиме ERROR используется формат из раздела выше про обработку ошибок.

Как логируем

Для каждого уровня логирования сделаны отдельные функции:

func PrintfInfoMsg(mes string, args ...interface{}) {
	printfMsg("[INFO]", 0, mes, args...)
}
func PrintfDebugMsg(mes string, args ...interface{}) {
	printfMsg("[DEBUG]", 0, mes, args...)
}
func PrintfErrorMsg(mes string, args ...interface{}) {
	printfMsg("[ERROR]", 0, mes, args...)
}

Это оказалось удобнее, чем в каждой точке логирования указывать уровень. Еще один плюс - легко централизовано отключить вывод DEBUG сообщений при переходе в продуктив.

Чтобы снизить затраты на логирование INFO и DEBUG, лучше отказаться от форматирования строк в точке вызова.
Вместо

mylog.PrintfInfoMsg(fmt.Sprintf("Create new TCP listener network='tcp', address='%s'", serverCfg.ListenSpec))

использовать

mylog.PrintfInfoMsg("Created new TCP listener: network = 'tcp', address", cfg.ListenSpec)

Тесты показали, что накладные расходы на вызовы логирования DEBUG в режиме INFO не превысили 1%, поэтому я перестал вычищать код от DEBUG вызовов перед переносом на прод. В этом есть существенный положительный момент - можно динамически изменить уровень с INFO на DEBUG без остановки сервера.

Дополнительное логирование трафика

Для анализа сложных ситуаций полезно иметь возможность логирования трафика проходящего через сервер. В пакете httplog собраны методы для логирования заголовков и тела:

  • входящего запроса
  • исходящего ответа
  • исходящего запроса
  • входящего ответа

Настройка типа логирования и лог файла может задаваться в конфигруационном файле - параметры HttpLog и HTTPLogType, или динамически вызовом POST на /httplog.

POST /httplog HTTP/1.1
Host: 127.0.0.1:3000
Http-Log: TRUE
Http-Log-Type: INREQ | OUTREQ | INRESP | OUTRESP | BODY

Аутентификация и JSON Web Token

В шаблон включены два способа аутентификации: HTTP Basic Authentication или MS AD Authentication. Для последней использовалась библиотека gopkg.in/korylprince/go-ad-auth.v2.
На уровне конфигурационного файла сервера можно задать тип аутентификации и параметры подключения к серверу MS AD.

[AUTHENTIFICATION]
AuthType = INTERNAL | MSAD | NONE
MSADServer = company.com
MSADPort = 389
MSADBaseDN = OU=company, DC=dc, DC=corp
MSADSecurity = SecurityNone

Пользователь и пароль для проверки HTTP Basic Authentication передается через командую строку при старте сервера.

Использование JSON Web Token (JWT) задается на уровне конфигурационного файла сервера. Время жизни токена задается JWTExpiresAt. Если JWTExpiresAt=0, то время жизни не огранчено. Секретная строка для генерации JWT передается через командую строку при старте сервера.

[JWT]
UseJWT = true
JWTExpiresAt = 20000

Для работы с JWT используется библиотека github.com/dgrijalva/jwt-go. Используется только один дополнительный JSON Web Token Claims - Username.
Вся обработка JWT: создание, проверка, формирование cookie собрано в небольшой кастомный пакет jwt

Для передачи токена клиенту использовалась cookie "token".

Если включен режим аутентификации без использования JWT токена, то проверять пользователя и пароль каждый раз

Организация кода и сборка

Библиотеки

Для организации библиотек перешел с golang/dep/cmd/dep на go mod, но для хранения библиотек по прежнему используется папка vendor в корне проекта. Это позволяет хранить "правильные" версии библиотек в своем репозитории проекта. Обновление библиотек выполняется командой.

go get -u ./../...
go mod vendor
  • rebuild - полная пересборка
  • build - инкрементальная сборка
  • check - проверка кода с использованием github.com/golangci/golangci-lint

При сборе в исполняемый файл внедряется номер версии программыверсия, дата сбори и номер commit. Эта инфорация выводится в лог файл - весьма полезно для разбора ошибок.
Для реализации такого внедрения, в main добавляем переменные

var (
	version   = "0.0.2" // номер версии, задается руками
	commit    = "unset" // номер commit
	buildTime = "unset" // дата и время сборки
	version   = "0.0.5" // номер версии, задается руками
	commit    = "unset"
	buildTime = "unset"
)

При сборе в make файле, запрашиваем git о номере commit

cmd/httpserver/bin/windows/httplog/http2020_03_10_115429.log

Whitespace-only changes.

cmd/httpserver/bin/windows/httplog/http2020_03_10_115437.log

Whitespace-only changes.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'2020.03.11 13:46:18-693804600' In Request '1' BEGIN ====================================================================
2+
POST /httplog HTTP/1.1
3+
Host: 127.0.0.1:3000
4+
Accept: */*
5+
Accept-Encoding: gzip, deflate, br
6+
Authorization: Basic cm9tYW46V2VsY29tZTE=
7+
Cache-Control: no-cache
8+
Connection: keep-alive
9+
Content-Length: 0
10+
Http-Log: true
11+
Http-Log-Type: INREQ | OUTREQ | INRESP | OUTRESP | BODY
12+
Postman-Token: dda52cba-31d1-4024-9f91-0ab4daee3c0d
13+
User-Agent: PostmanRuntime/7.22.0
14+
15+
16+
'2020.03.11 13:46:18-694802000' In Request '1' End ====================================================================
17+
'2020.03.11 13:46:18-695800800' Out Response '1' BEGIN ====================================================================
18+
HTTP 200 OK
19+
Errcode: 0
20+
RequestID: 1
21+
22+
23+
'2020.03.11 13:46:18-699790100' Out Response '1' End ====================================================================
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'2020.03.11 14:00:43-602222400' Out Response '1' BEGIN ====================================================================
2+
HTTP 200 OK
3+
Errcode: 0
4+
RequestID: 1
5+
6+
7+
'2020.03.11 14:00:43-602222400' Out Response '1' End ====================================================================
8+
'2020.03.11 14:00:57-649062200' In Request '2' BEGIN ====================================================================
9+
POST /httplog HTTP/1.1
10+
Host: 127.0.0.1:3000
11+
Accept: */*
12+
Accept-Encoding: gzip, deflate, br
13+
Authorization: Basic cm9tYW4xOldlbGNvbWUx
14+
Cache-Control: no-cache
15+
Connection: keep-alive
16+
Content-Length: 0
17+
Http-Log: true
18+
Http-Log-Type: INREQ | OUTREQ | INRESP | OUTRESP | BODY
19+
Postman-Token: 17928bb0-5409-4337-aac5-65ea92c72c09
20+
User-Agent: PostmanRuntime/7.22.0
21+
22+
23+
'2020.03.11 14:00:57-653051100' In Request '2' End ====================================================================
24+
'2020.03.11 14:01:36-262225400' In Request '3' BEGIN ====================================================================
25+
POST /httplog HTTP/1.1
26+
Host: 127.0.0.1:3000
27+
Accept: */*
28+
Accept-Encoding: gzip, deflate, br
29+
Authorization: Basic cm9tYW46V2VsY29tZTE=
30+
Cache-Control: no-cache
31+
Connection: keep-alive
32+
Content-Length: 0
33+
Http-Log: true
34+
Http-Log-Type: INREQ | OUTREQ | INRESP | OUTRESP | BODY
35+
Postman-Token: d10af9a7-4c11-4bbc-bc13-64008b53a97a
36+
User-Agent: PostmanRuntime/7.22.0
37+
38+
39+
'2020.03.11 14:01:36-262225400' In Request '3' End ====================================================================
40+
'2020.03.11 14:01:36-279178200' Out Response '3' BEGIN ====================================================================
41+
HTTP 200 OK
42+
Errcode: 0
43+
RequestID: 3
44+
45+
46+
'2020.03.11 14:01:36-279178200' Out Response '3' End ====================================================================
47+
'2020.03.11 14:01:53-273742600' In Request '4' BEGIN ====================================================================
48+
POST /httplog HTTP/1.1
49+
Host: 127.0.0.1:3000
50+
Accept: */*
51+
Accept-Encoding: gzip, deflate, br
52+
Authorization: Basic cm9tYW4xOldlbGNvbWUx
53+
Cache-Control: no-cache
54+
Connection: keep-alive
55+
Content-Length: 0
56+
Http-Log: true
57+
Http-Log-Type: INREQ | OUTREQ | INRESP | OUTRESP | BODY
58+
Postman-Token: 84b0f473-6acd-48ce-b9d8-1b28031a44c8
59+
User-Agent: PostmanRuntime/7.22.0
60+
61+
62+
'2020.03.11 14:01:53-273742600' In Request '4' End ====================================================================

cmd/httpserver/bin/windows/httplog/http2020_03_10_110617.log renamed to cmd/httpserver/bin/windows/httplog/http2020_03_11_141048.log

File renamed without changes.

cmd/httpserver/bin/windows/httplog/http2020_03_10_114353.log renamed to cmd/httpserver/bin/windows/httplog/http2020_03_11_170359.log

File renamed without changes.

cmd/httpserver/bin/windows/httplog/http2020_03_10_114640.log renamed to cmd/httpserver/bin/windows/httplog/http2020_03_11_170707.log

File renamed without changes.

cmd/httpserver/bin/windows/httplog/http2020_03_10_115058.log renamed to cmd/httpserver/bin/windows/httplog/http2020_03_11_170923.log

File renamed without changes.

cmd/httpserver/bin/windows/httpserver.cfg

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ TLSMinVersion = VersionTLS10
1616
TLSMaxVersion = VersionTLS12
1717

1818
[JWT]
19-
UseJWT = false
20-
JWTExpiresAt = 20000
19+
UseJWT = true
20+
JWTExpiresAt = 20
2121

2222
[AUTHENTIFICATION]
23-
AuthType = NONE
24-
MSADServer = seliger.borlas.corp
23+
AuthType = INTERNAL
24+
MSADServer = company.com
2525
MSADPort = 389
26-
MSADBaseDN = OU=Borlas, DC=borlas, DC=corp
26+
MSADBaseDN = OU=company, DC=dc, DC=corp
2727
MSADSecurity = SecurityNone
2828

2929
[LOG]
30-
HTTPLog = true
30+
HTTPLog = false
3131
HTTPLogType = INREQ | OUTREQ | INRESP | OUTRESP | BODY
3232
HTTPLogFileName = ./httplog/http%s.log
3333
HTTPErrLog = HEADER | BODY

0 commit comments

Comments
 (0)