All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fizzgate.dedicated_line.DedicatedLineController Maven / Gradle / Ivy

/*
 *  Copyright (C) 2020 the original author or authors.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see .
 */

package com.fizzgate.dedicated_line;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.server.ServerWebExchange;

import com.fizzgate.config.FizzMangerConfig;
import com.fizzgate.config.SystemConfig;
import com.fizzgate.proxy.FizzWebClient;
import com.fizzgate.util.*;

import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * @author hongqiaowei
 */

@ConditionalOnProperty(name = SystemConfig.FIZZ_DEDICATED_LINE_SERVER_ENABLE, havingValue = "true")
@RestController
@RequestMapping(SystemConfig.DEFAULT_GATEWAY_PREFIX + "/_fizz-dedicated-line")
public class DedicatedLineController {

    private static final Logger log = LoggerFactory.getLogger(DedicatedLineController.class);

    @Resource
    private SystemConfig            systemConfig;

    @Resource
    private DedicatedLineService    dedicatedLineService;

    @Resource
    private FizzMangerConfig        fizzMangerConfig;

    @Resource
    private FizzWebClient           fizzWebClient;

    private Result auth(ServerWebExchange exchange) {
        String dedicatedLineId = WebUtils.getDedicatedLineId(exchange);
        if (dedicatedLineId == null) {
            return Result.fail("no dedicated line id in request");
        }

        String timestamp = WebUtils.getDedicatedLineTimestamp(exchange);
        if (timestamp == null) {
            return Result.fail("no timestamp in request");
        }
        try {
            long ts = Long.parseLong(timestamp);
            LocalDateTime now = LocalDateTime.now();
            long timeliness = systemConfig.fizzDedicatedLineClientRequestTimeliness();
            long start = DateTimeUtils.toMillis(now.minusSeconds(timeliness));
            long end   = DateTimeUtils.toMillis(now.plusSeconds (timeliness));
            if (start <= ts && ts <= end) {
                // valid
            } else {
                return Result.fail("request timestamp invalid");
            }
        } catch (NumberFormatException e) {
            return Result.fail("request timestamp format invalid");
        }

        String sign = WebUtils.getDedicatedLineSign(exchange);
        if (sign == null) {
            return Result.fail("no sign in request");
        }

        String pairCodeSecretKey = dedicatedLineService.getSignSecretKey(dedicatedLineId);
        boolean equals = DedicatedLineUtils.checkSign(dedicatedLineId, timestamp, pairCodeSecretKey, sign);
        if (!equals) {
            String traceId = WebUtils.getTraceId(exchange);
            // log.warn("{} request authority: dedicated line id {}, timestamp {}, sign {} invalid", traceId, dedicatedLineId, timestamp, sign, LogService.BIZ_ID, traceId);
            org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId);
            log.warn("{} request authority: dedicated line id {}, timestamp {}, sign {} invalid", traceId, dedicatedLineId, timestamp, sign);
            return Result.fail("request sign invalid");
        }
        return Result.succ();
    }

    @GetMapping("/pair")
    public Mono pair(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String managerUrl = fizzMangerConfig.managerUrl;
        if (managerUrl == null) {
            return WebUtils.response(response, HttpStatus.INTERNAL_SERVER_ERROR, null, "no fizz manager url config");
        }
        String address = managerUrl + fizzMangerConfig.pairPath;

        String traceId = WebUtils.getTraceId(exchange);
        Mono remoteResponseMono = fizzWebClient.send(traceId, request.getMethod(), address, request.getHeaders(), null);
        return
                remoteResponseMono.flatMap(
                        remoteResp -> {
                            response.setStatusCode(remoteResp.statusCode());
                            HttpHeaders respHeaders = response.getHeaders();
                            HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders();
                            respHeaders.putAll(remoteRespHeaders);
                            if (log.isDebugEnabled()) {
                                StringBuilder sb = ThreadContext.getStringBuilder();
                                WebUtils.response2stringBuilder(traceId, remoteResp, sb);
                                // log.debug(sb.toString(), LogService.BIZ_ID, traceId);
                                org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId);
                                log.debug(sb.toString());
                            }
                            return response.writeWith (  remoteResp.body(BodyExtractors.toDataBuffers()) )
                                           .doOnError (   throwable -> cleanup(remoteResp)               )
                                           .doOnCancel(          () -> cleanup(remoteResp)               );
                        }
                );
    }

    @GetMapping("/doc/**")
    public Mono doc(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        Result auth = auth(exchange);
        if (auth.code == Result.SUCC) {
            String managerUrl = fizzMangerConfig.managerUrl;
            if (managerUrl == null) {
                return WebUtils.response(response, HttpStatus.INTERNAL_SERVER_ERROR, null, "no fizz manager url config");
            }
            ServerHttpRequest request = exchange.getRequest();
            String uri = request.getURI().toString();
            int dp = uri.indexOf("doc");
            String address = managerUrl + fizzMangerConfig.docPathPrefix + uri.substring(dp + 3);

            String traceId = WebUtils.getTraceId(exchange);
            Mono remoteResponseMono = fizzWebClient.send(traceId, request.getMethod(), address, request.getHeaders(), null);
            return
                   remoteResponseMono.flatMap(
                                             remoteResp -> {
                                                 response.setStatusCode(remoteResp.statusCode());
                                                 HttpHeaders respHeaders = response.getHeaders();
                                                 HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders();
                                                 respHeaders.putAll(remoteRespHeaders);
                                                 if (log.isDebugEnabled()) {
                                                     StringBuilder sb = ThreadContext.getStringBuilder();
                                                     WebUtils.response2stringBuilder(traceId, remoteResp, sb);
                                                     // log.debug(sb.toString(), LogService.BIZ_ID, traceId);
                                                     org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId);
                                                     log.debug(sb.toString());
                                                 }
                                                 return response.writeWith (  remoteResp.body(BodyExtractors.toDataBuffers()) )
                                                                .doOnError (   throwable -> cleanup(remoteResp)               )
                                                                .doOnCancel(          () -> cleanup(remoteResp)               );
                                             }
                                     );

        } else {
            return WebUtils.response(response, HttpStatus.FORBIDDEN, null, auth.msg);
        }
    }

    private void cleanup(ClientResponse clientResponse) {
        if (clientResponse != null) {
            clientResponse.bodyToMono(Void.class).subscribe();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy