自定义exporter使用HTTPServer实现简单basic auth

自定义exporter使用HTTPServer实现简单basic auth

先上效果图:输入账号密码后才暴露metrics指标;
在这里插入图片描述
官方当前版本(我的是0.15.0) 已支持通过Authenticator验证来实现basic auth验证;但没有放出实现方法;我们只需复制出一份HTTPServer,修改一下,然后替换掉官方的依赖就行了;下面直接上源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.inspur.ftpservice.Config;

import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.*;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.Predicate;
import io.prometheus.client.SampleNameFilter;
import io.prometheus.client.Supplier;
import io.prometheus.client.exporter.SampleNameFilterSupplier;
import io.prometheus.client.exporter.common.TextFormat;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPOutputStream;

public class HTTPServer implements Closeable {
    protected final HttpServer server;
    protected final ExecutorService executorService;

    protected static boolean shouldUseCompression(HttpExchange exchange) {
        List<String> encodingHeaders = exchange.getRequestHeaders().get("Accept-Encoding");
        if (encodingHeaders == null) {
            return false;
        } else {
            Iterator var2 = encodingHeaders.iterator();

            while(var2.hasNext()) {
                String encodingHeader = (String)var2.next();
                String[] encodings = encodingHeader.split(",");
                String[] var5 = encodings;
                int var6 = encodings.length;

                for(int var7 = 0; var7 < var6; ++var7) {
                    String encoding = var5[var7];
                    if (encoding.trim().equalsIgnoreCase("gzip")) {
                        return true;
                    }
                }
            }

            return false;
        }
    }

    protected static Set<String> parseQuery(String query) throws IOException {
        Set<String> names = new HashSet();
        if (query != null) {
            String[] pairs = query.split("&");
            String[] var3 = pairs;
            int var4 = pairs.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                String pair = var3[var5];
                int idx = pair.indexOf("=");
                if (idx != -1 && URLDecoder.decode(pair.substring(0, idx), "UTF-8").equals("name[]")) {
                    names.add(URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
                }
            }
        }

        return names;
    }

    public HTTPServer(HttpServer httpServer, CollectorRegistry registry, boolean daemon,Authenticator authenticator) throws IOException {
        this(httpServer, registry, daemon, (Supplier)null, authenticator);
    }

    public HTTPServer(InetSocketAddress addr, CollectorRegistry registry, boolean daemon) throws IOException {
        this(HttpServer.create(addr, 3), registry, daemon,null);
    }

    public HTTPServer(InetSocketAddress addr, CollectorRegistry registry) throws IOException {
        this(addr, registry, false);
    }

    public HTTPServer(int port, boolean daemon) throws IOException {
        this(new InetSocketAddress(port), CollectorRegistry.defaultRegistry, daemon);
    }

    public HTTPServer(int port) throws IOException {
        this(port, false);
    }

    public HTTPServer(String host, int port, boolean daemon) throws IOException {
        this(new InetSocketAddress(host, port), CollectorRegistry.defaultRegistry, daemon);
    }

    public HTTPServer(String host, int port) throws IOException {
        this(new InetSocketAddress(host, port), CollectorRegistry.defaultRegistry, false);
    }

    public HTTPServer(HttpServer httpServer, CollectorRegistry registry, boolean daemon, Supplier<Predicate<String>> sampleNameFilterSupplier, Authenticator authenticator) {
        if (httpServer.getAddress() == null) {
            throw new IllegalArgumentException("HttpServer hasn't been bound to an address");
        } else {
            this.server = httpServer;
            HttpHandler mHandler = new HTTPServer.HTTPMetricHandler(registry, sampleNameFilterSupplier);
            HttpContext mContext = this.server.createContext("/", mHandler);
            if (authenticator != null) {
                mContext.setAuthenticator(authenticator);
            }

            mContext = this.server.createContext("/metrics", mHandler);
            if (authenticator != null) {
                mContext.setAuthenticator(authenticator);
            }

            mContext = this.server.createContext("/-/healthy", mHandler);
            if (authenticator != null) {
                mContext.setAuthenticator(authenticator);
            }

            this.executorService = Executors.newFixedThreadPool(5, HTTPServer.NamedDaemonThreadFactory.defaultThreadFactory(daemon));
            this.server.setExecutor(this.executorService);
            this.start(daemon);
        }
    }

    private void start(boolean daemon) {
        if (daemon == Thread.currentThread().isDaemon()) {
            this.server.start();
        } else {
            FutureTask<Void> startTask = new FutureTask(new Runnable() {
                public void run() {
                    HTTPServer.this.server.start();
                }
            }, (Object)null);
            HTTPServer.NamedDaemonThreadFactory.defaultThreadFactory(daemon).newThread(startTask).start();

            try {
                startTask.get();
            } catch (ExecutionException var4) {
                throw new RuntimeException("Unexpected exception on starting HTTPSever", var4);
            } catch (InterruptedException var5) {
                Thread.currentThread().interrupt();
            }
        }

    }

    /** @deprecated */
    public void stop() {
        this.close();
    }

    public void close() {
        this.server.stop(0);
        this.executorService.shutdown();
    }

    public int getPort() {
        return this.server.getAddress().getPort();
    }

    static {
        if (!System.getProperties().containsKey("sun.net.httpserver.maxReqTime")) {
            System.setProperty("sun.net.httpserver.maxReqTime", "60");
        }

        if (!System.getProperties().containsKey("sun.net.httpserver.maxRspTime")) {
            System.setProperty("sun.net.httpserver.maxRspTime", "600");
        }

    }

    public static class Builder {
        private int port = 0;
        private String hostname = null;
        private InetAddress inetAddress = null;
        private InetSocketAddress inetSocketAddress = null;
        private HttpServer httpServer = null;
        private CollectorRegistry registry;
        private boolean daemon;
        private Predicate<String> sampleNameFilter;
        private Supplier<Predicate<String>> sampleNameFilterSupplier;
        private Authenticator authenticator;
        private HttpsConfigurator httpsConfigurator;

        public Builder() {
            this.registry = CollectorRegistry.defaultRegistry;
            this.daemon = false;
        }

        public HTTPServer.Builder withPort(int port) {
            this.port = port;
            return this;
        }

        public HTTPServer.Builder withHostname(String hostname) {
            this.hostname = hostname;
            return this;
        }

        public HTTPServer.Builder withInetAddress(InetAddress address) {
            this.inetAddress = address;
            return this;
        }

        public HTTPServer.Builder withInetSocketAddress(InetSocketAddress address) {
            this.inetSocketAddress = address;
            return this;
        }

        public HTTPServer.Builder withHttpServer(HttpServer httpServer) {
            this.httpServer = httpServer;
            return this;
        }

        public HTTPServer.Builder withDaemonThreads(boolean daemon) {
            this.daemon = daemon;
            return this;
        }

        public HTTPServer.Builder withSampleNameFilter(Predicate<String> sampleNameFilter) {
            this.sampleNameFilter = sampleNameFilter;
            return this;
        }

        public HTTPServer.Builder withSampleNameFilterSupplier(Supplier<Predicate<String>> sampleNameFilterSupplier) {
            this.sampleNameFilterSupplier = sampleNameFilterSupplier;
            return this;
        }

        public HTTPServer.Builder withRegistry(CollectorRegistry registry) {
            this.registry = registry;
            return this;
        }

        public HTTPServer.Builder withAuthenticator(Authenticator authenticator) {
            this.authenticator = authenticator;
            return this;
        }

        public HTTPServer.Builder withHttpsConfigurator(HttpsConfigurator configurator) {
            this.httpsConfigurator = configurator;
            return this;
        }

        public HTTPServer build() throws IOException {
            if (this.sampleNameFilter != null) {
                this.assertNull(this.sampleNameFilterSupplier, "cannot configure 'sampleNameFilter' and 'sampleNameFilterSupplier' at the same time");
                this.sampleNameFilterSupplier = SampleNameFilterSupplier.of(this.sampleNameFilter);
            }

            if (this.httpServer != null) {
                this.assertZero(this.port, "cannot configure 'httpServer' and 'port' at the same time");
                this.assertNull(this.hostname, "cannot configure 'httpServer' and 'hostname' at the same time");
                this.assertNull(this.inetAddress, "cannot configure 'httpServer' and 'inetAddress' at the same time");
                this.assertNull(this.inetSocketAddress, "cannot configure 'httpServer' and 'inetSocketAddress' at the same time");
                this.assertNull(this.httpsConfigurator, "cannot configure 'httpServer' and 'httpsConfigurator' at the same time");
                return new HTTPServer(this.httpServer, this.registry, this.daemon, this.sampleNameFilterSupplier, this.authenticator);
            } else {
                if (this.inetSocketAddress != null) {
                    this.assertZero(this.port, "cannot configure 'inetSocketAddress' and 'port' at the same time");
                    this.assertNull(this.hostname, "cannot configure 'inetSocketAddress' and 'hostname' at the same time");
                    this.assertNull(this.inetAddress, "cannot configure 'inetSocketAddress' and 'inetAddress' at the same time");
                } else if (this.inetAddress != null) {
                    this.assertNull(this.hostname, "cannot configure 'inetAddress' and 'hostname' at the same time");
                    this.inetSocketAddress = new InetSocketAddress(this.inetAddress, this.port);
                } else if (this.hostname != null) {
                    this.inetSocketAddress = new InetSocketAddress(this.hostname, this.port);
                } else {
                    this.inetSocketAddress = new InetSocketAddress(this.port);
                }

                HttpServer httpServer = null;
                if (this.httpsConfigurator != null) {
                    httpServer = HttpsServer.create(this.inetSocketAddress, 3);
                    ((HttpsServer)httpServer).setHttpsConfigurator(this.httpsConfigurator);
                } else {
                    httpServer = HttpServer.create(this.inetSocketAddress, 3);
                }

                return new HTTPServer((HttpServer)httpServer, this.registry, this.daemon, this.sampleNameFilterSupplier, this.authenticator);
            }
        }

        private void assertNull(Object o, String msg) {
            if (o != null) {
                throw new IllegalStateException(msg);
            }
        }

        private void assertZero(int i, String msg) {
            if (i != 0) {
                throw new IllegalStateException(msg);
            }
        }
    }

    static class NamedDaemonThreadFactory implements ThreadFactory {
        private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
        private final int poolNumber;
        private final AtomicInteger threadNumber;
        private final ThreadFactory delegate;
        private final boolean daemon;

        NamedDaemonThreadFactory(ThreadFactory delegate, boolean daemon) {
            this.poolNumber = POOL_NUMBER.getAndIncrement();
            this.threadNumber = new AtomicInteger(1);
            this.delegate = delegate;
            this.daemon = daemon;
        }

        public Thread newThread(Runnable r) {
            Thread t = this.delegate.newThread(r);
            t.setName(String.format("prometheus-http-%d-%d", this.poolNumber, this.threadNumber.getAndIncrement()));
            t.setDaemon(this.daemon);
            return t;
        }

        static ThreadFactory defaultThreadFactory(boolean daemon) {
            return new HTTPServer.NamedDaemonThreadFactory(Executors.defaultThreadFactory(), daemon);
        }
    }

    public static class HTTPMetricHandler implements HttpHandler {
        private final CollectorRegistry registry;
        private final HTTPServer.LocalByteArray response;
        private final Supplier<Predicate<String>> sampleNameFilterSupplier;
        private static final String HEALTHY_RESPONSE = "Exporter is Healthy.";

        public HTTPMetricHandler(CollectorRegistry registry) {
            this(registry, (Supplier)null);
        }

        public HTTPMetricHandler(CollectorRegistry registry, Supplier<Predicate<String>> sampleNameFilterSupplier) {
            this.response = new HTTPServer.LocalByteArray();
            this.registry = registry;
            this.sampleNameFilterSupplier = sampleNameFilterSupplier;
        }

        public void handle(HttpExchange t) throws IOException {
            String query = t.getRequestURI().getRawQuery();
            String contextPath = t.getHttpContext().getPath();
            ByteArrayOutputStream response = (ByteArrayOutputStream)this.response.get();
            response.reset();
            OutputStreamWriter osw = new OutputStreamWriter(response, Charset.forName("UTF-8"));
            if ("/-/healthy".equals(contextPath)) {
                osw.write("Exporter is Healthy.");
            } else {
                String contentType = TextFormat.chooseContentType(t.getRequestHeaders().getFirst("Accept"));
                t.getResponseHeaders().set("Content-Type", contentType);
                Predicate<String> filter = this.sampleNameFilterSupplier == null ? null : (Predicate)this.sampleNameFilterSupplier.get();
                filter = SampleNameFilter.restrictToNamesEqualTo(filter, HTTPServer.parseQuery(query));
                if (filter == null) {
                    TextFormat.writeFormat(contentType, osw, this.registry.metricFamilySamples());
                } else {
                    TextFormat.writeFormat(contentType, osw, this.registry.filteredMetricFamilySamples(filter));
                }
            }

            osw.close();
            if (HTTPServer.shouldUseCompression(t)) {
                t.getResponseHeaders().set("Content-Encoding", "gzip");
                t.sendResponseHeaders(200, 0L);
                GZIPOutputStream os = new GZIPOutputStream(t.getResponseBody());

                try {
                    response.writeTo(os);
                } finally {
                    os.close();
                }
            } else {
                long contentLength = (long)response.size();
                if (contentLength > 0L) {
                    t.getResponseHeaders().set("Content-Length", String.valueOf(contentLength));
                }

                if (t.getRequestMethod().equals("HEAD")) {
                    contentLength = -1L;
                }

                t.sendResponseHeaders(200, contentLength);
                response.writeTo(t.getResponseBody());
            }

            t.close();
        }
    }

    private static class LocalByteArray extends ThreadLocal<ByteArrayOutputStream> {
        private LocalByteArray() {
        }

        protected ByteArrayOutputStream initialValue() {
            return new ByteArrayOutputStream(1048576);
        }
    }
}

实现如下:
这里的HTTP_USER和HTTP_PASSWORD可以自己定义,密码是以明文的方式

		new SFTPCollector().register();
        Authenticator authenticator = new BasicAuthenticator("/") {
            @Override
            public boolean checkCredentials(String user, String password) {
                return HTTP_USER.equals(user) && HTTP_PASSWORD.equals(password);
            }
        };
        HTTPServer server = new HTTPServer.Builder().withPort(18081).withAuthenticator(authenticator).build();

ok,大功告成!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【课程特点】1、231节大容量课程:包含了SwiftUI的大部分知识点,详细讲解SwiftUI的方方面面;2、15个超级精彩的实例:包含美食、理财、健身、教育、电子商务等各行业的App实例;3、创新的教学模式:手把手教您SwiftUI用户界面开发技术,一看就懂,一学就会;4、贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标;5、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间;6、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索;7、齐全的学习资料:提供所有课程的源码,在Xcode 11 + iOS 13环境下测试通过; 更好的应用,更少的代码!SwiftUI是苹果主推的下一代用户界面搭建技术,具有声明式语法、实时生成界面预览等特性,可以为苹果手机、苹果平板、苹果电脑、苹果电视、苹果手表五个平台搭建统一的用户界面。SwiftUI是一种创新、简单的iOS开发中的界面布局方案,可以通过Swift语言的强大功能,在所有的Apple平台上快速构建用户界面。 仅使用一组工具和API为任何Apple设备构建用户界面。SwiftUI具有易于阅读和自然编写的声明式Swift语法,可与新的Xcode设计工具无缝协作,使您的代码和设计**同步。自动支持动态类型、暗黑模式、本地化和可访问性,意味着您的**行SwiftUI代码已经是您编写过的非常强大的UI代码了。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值