diff --git a/src/main/java/net/geedge/confagent/controller/PromtailController.java b/src/main/java/net/geedge/confagent/controller/PromtailController.java index ee656a5..3e7ac0e 100644 --- a/src/main/java/net/geedge/confagent/controller/PromtailController.java +++ b/src/main/java/net/geedge/confagent/controller/PromtailController.java @@ -1,6 +1,12 @@ package net.geedge.confagent.controller; +import cn.hutool.core.net.url.UrlBuilder; +import cn.hutool.core.net.url.UrlPath; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpConnection; import cn.hutool.log.Log; +import net.geedge.confagent.annotation.UnCheckToken; import net.geedge.confagent.util.ConfagentUtil; import net.geedge.confagent.util.R; import net.geedge.confagent.util.RCode; @@ -11,8 +17,18 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.nio.charset.Charset; import java.util.*; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + @RestController @RequestMapping("/promtail") public class PromtailController extends BaseController{ @@ -36,6 +52,8 @@ public class PromtailController extends BaseController{ @Value("${confagent.promtail.stopCmd:systemctl stop promtail.service}") private String stopCmd; + private final String[] QUERY_API_SUFFIX = {"query","query_range","series","labels","label","values"}; + private static String rootPath = Tool.WebPathUtil.getRootPath(); /** @@ -148,16 +166,104 @@ public class PromtailController extends BaseController{ } -// private boolean reloadPromtail(){ -// -// UrlBuilder promtailReload = new UrlBuilder(); -// int promtailPort = ConfagentUtil.getConfFilePort(promtailCmdLinePath, PROMTAIL_LISTEN_ADDR, DEFAULT_PROMTAIL_PORT); -// promtailReload.setScheme("http").setHost(defaultPromtailIP).setPort(promtailPort).addPath("/-/reload"); -// -// String url = promtailReload.toString(); -// HttpRequest post = Tool.HttpUtil.createPost(url); -// HttpResponse response = post.execute(); -// return 200 == response.getStatus(); -// } + /** + * @Description 代理本promtail 接口 + * @Author han + * @Date 2021/8/10 + */ + @RequestMapping("/proxy/**") + @UnCheckToken + public void proxy(HttpServletRequest request, HttpServletResponse response){ + String promtailPath = request.getServletPath().replace("/promtail/proxy",""); + String token = request.getHeader("Authorization"); + + R r = confagentUtil.checkToken(token); + + Boolean isQuery=false; + + //queryAuth 配置只限制查询是否需要校验 + if(queryAuth){ + isQuery = Tool.StrUtil.isNotBlank(Arrays.stream(QUERY_API_SUFFIX).filter(t -> promtailPath.indexOf(t) != -1).findAny().orElse(null)); + } + + if(isQuery &&r.getCode() != RCode.SUCCESS.getCode()){ + ConfagentUtil.writeResponse(response,r); + return; + } + + int port = 9080; + Map promtailMap= Tool.YamlUtil.readAsMap(promtailConfPath); + Map serverObj = (Map)promtailMap.get("server"); + if(serverObj!=null) { + port = (Integer)serverObj.get("http_listen_port"); + } + + requestProm(defaultPromtailIP,port,promtailPath,request,response); + + } + + public void requestProm(String host, int port, String path, HttpServletRequest request, HttpServletResponse response) { + String queryString = ReflectUtil.invoke(request, "getQueryString"); + queryString = StrUtil.isNotBlank(queryString)?queryString:""; + String url = UrlBuilder.create().setScheme("http").setHost(host).setPort(port).setPath(UrlPath.of(path, Charset.forName("UTF-8"))).toURL().toString() + "?" + queryString; + + log.info("promtail url: {}", url); + String method = request.getMethod(); + HttpURLConnection conn = null; + ServletInputStream reqInputStream = null; + ServletOutputStream resOutputStream = null; + OutputStream connOutputStream = null; + InputStream connInputStream = null; + try { + conn = HttpConnection.create(url, null).getHttpURLConnection(); + reqInputStream = request.getInputStream(); + resOutputStream = response.getOutputStream(); + conn.setRequestMethod(method); + // 复制请求头 + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String hn = headerNames.nextElement(); + if(!"authorization".equalsIgnoreCase(hn)) { + ReflectUtil.invoke(conn,"addRequestProperty",hn,request.getHeader(hn)); + } + } + + if (!"GET".equalsIgnoreCase(method)) { + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setUseCaches(false); + connOutputStream = conn.getOutputStream(); + Tool.IoUtil.copy(reqInputStream, connOutputStream); + } + conn.connect(); + int responseCode = conn.getResponseCode(); + connInputStream = (responseCode < 400)? conn.getInputStream():conn.getErrorStream(); + String responseMessage = conn.getResponseMessage(); + Map> responseHeaders = conn.getHeaderFields(); + //复制响应头 + for(Map.Entry> en : responseHeaders.entrySet()) { + String key = en.getKey(); + if (Tool.StrUtil.isEmpty(key) || "Transfer-Encoding".equals(key)) continue; + List value = en.getValue(); + ReflectUtil.invoke(response,"addHeader",key,Tool.StrUtil.join("; ",value)); + } + ReflectUtil.invoke(response, "setStatus", responseCode, responseMessage); + + Tool.IoUtil.copy(connInputStream, resOutputStream); + resOutputStream.flush();//flush 输出流 + } catch (Exception e) { + try { + response.sendError(500, "request error"); + } catch (IOException e1) { + log.error("proxy request error",e1); + } + log.error("request error : ",e); + }finally { + Tool.IoUtil.close(reqInputStream,resOutputStream,connOutputStream,connInputStream); + if(conn != null){ + conn.disconnect(); + } + } + } }