网络

本指南展示了如何使用与网络相关的功能,例如代理、网络事件、身份验证、TLS、客户端证书身份验证等。

可以通过网络实例访问网络相关功能,Network 实例可以使用以下方式获取:

Network network = profile.network();
val network = profile.network()

接受语言

JxBrowser 允许通过Network.acceptLanguage(String) 方法配置 Accept-Language HTTP 标头值。

例如,“fr, en-gb;q=0.8, en;q=0.7” 值表示:“I prefer French, but will accept British English, and other types of English”:

network.acceptLanguage("fr, en-gb;q=0.8, en;q=0.7");
network.acceptLanguage("fr, en-gb;q=0.8, en;q=0.7")

服务器白名单

HTTP 服务器授权白名单

您可以配置 HTTP 服务器授权白名单,该白名单表示带有逗号/分号分隔 URL 列表的字符串。 例如:

network.httpAuthPreferences().serverWhitelist("*google.com,*example.com,*baz");
network.httpAuthPreferences().serverWhitelist("*google.com,*example.com,*baz")

HTTP 网络代理白名单

要配置 HTTP 网络委托白名单,您可以使用下面描述的方法:

network.httpAuthPreferences().delegateWhitelist("*google.com,*example.com,*baz");
network.httpAuthPreferences().delegateWhitelist("*google.com,*example.com,*baz")

TLS(传输层安全性协议)

证书验证

默认情况下,Chromium 会验证在网页加载期间从网络服务器获得的所有 SSL 证书。 JxBrowser 允许修改此默认行为并控制验证过程。

要处理证书验证,请使用 VerifyCertificateCallback 回调。 在调用此回调之前,Chromium 会验证 SSL 证书并将验证结果提供给回调。 根据验证结果,回调会收到 SSL 证书本身。 您可以验证给定的 SSL 证书并将验证结果通知引擎。

例如:

network.set(VerifyCertificateCallback.class, (params) -> {
    // SSL Certificate to verify.
    Certificate certificate = params.certificate();
    // The results of the verification performed by default verifier.
    List<CertVerificationError> verificationErrors =
        params.verificationErrors();
    // The results of default verification should be used.
    return Response.defaultAction();
});
network.set(VerifyCertificateCallback::class.java, VerifyCertificateCallback { params ->
    // SSL Certificate to verify.
    val certificate = params.certificate()
    // The results of the verification performed by default verifier.
    val verificationErrors = params.verificationErrors()
    // The results of default verification should be used.
    Response.defaultAction()
})

客户端证书认证

JxBrowser 支持使用 HTTPS 客户端证书进行身份验证。 有关详细信息,请查看身份验证指南。

方案

该库提供了一个 API,允许注册自定义方案并使用 HTTP 或 HTTPS 等标准方案拦截 URL 请求。

在这两种情况下,具有相应方案的 URL 请求将被拦截,并且将提供响应数据,就好像它是从网络 服务器发送的一样。 使用此功能,您可以模拟来自远程服务器的响应并使用一种本地网络服务器。

注册自定义方案

要注册自定义方案,请在配置 Engine 期间使用 EngineOptions.Builder.addScheme() 方法。 这是必需的,因为 Chromium 在启动期间注册了所有方案,并且在初始化后不允许修改方案。

以下代码演示了如何注册自定义方案并关联 InterceptUrlRequestCallback 回调,每次浏览器通过具有给定方案的 URL 加载资源时都会调用该回调:

EngineOptions options = EngineOptions
        .newBuilder(renderingMode)
        .addScheme(Scheme.of("jxb"), params -> {
            UrlRequestJob job = params.newUrlRequestJob(
                    UrlRequestJob.Options
                            .newBuilder(HttpStatus.OK)
                            .addHttpHeader(HttpHeader.of("Content-Type", "text/plain"))
                            .build());
            job.write("Hello!".getBytes());
            job.complete();
            return Response.intercept(job);
        })
        .build();
Engine engine = Engine.newInstance(options);
val options = EngineOptions
        .newBuilder(renderingMode)
        .addScheme(Scheme.of("jxb"), InterceptUrlRequestCallback { params ->
            val job = params.newUrlRequestJob(
                    UrlRequestJob.Options
                            .newBuilder(HttpStatus.OK)
                            .addHttpHeader(HttpHeader.of("Content-Type", "text/plain"))
                            .build())
            job.write("Hello!".toByteArray())
            job.complete()
            Response.intercept(job)
        })
        .build()
val engine = Engine.newInstance(options)

现在,如果您加载 jxb://anyhost/anypage.html,URL 请求将被拦截,并调用关联的回调。 您将获得以下输出:

Custom Scheme

拦截 HTTP/HTTPS 请求

您可以使用与注册自定义方案相同的方法来拦截标准方案,例如 HTTP 或 HTTPS。 在这种情况下,您需要添加相应的方案,如下所示:

EngineOptions options = EngineOptions
        .newBuilder(renderingMode)
        .addScheme(Scheme.HTTPS, params -> {
            UrlRequestJob job = params.newUrlRequestJob(...);
            ...
            return Response.intercept(job);
        })
        ...
EngineOptions options = EngineOptions
        .newBuilder(renderingMode)
        .addScheme(Scheme.HTTPS, InterceptUrlRequestCallback { params ->
            val job = params.newUrlRequestJob(...);
            ...
            Response.intercept(job)
        })
        ...

网络事件和回调

Network API 定义了一组遵循网络请求生命周期的事件和回调。 您可以使用这些事件来观察和分析流量。 回调将允许您拦截、阻止或修改请求。

请求成功的事件生命周期如下所示: Network Events Flow

在 URL 请求之前

BeforeUrlRequestCallback 回调在 HTTP 请求即将发生时被调用。 您可以使用此回调将请求重定向到另一个位置。 例如:

network.set(BeforeUrlRequestCallback.class, (params) ->
        Response.redirect("<new-url>"));
network.set(BeforeUrlRequestCallback::class.java,
    BeforeUrlRequestCallback {  Response.redirect("<new-url>") }
)

发送上传数据前

BeforeSendUploadDataCallback 回调在上传数据发送到网络服务器之前被调用。 您可以在此处覆盖上传数据。 例如:

network.set(BeforeSendUploadDataCallback.class, (params) ->
        Response.override(TextData.of("<text-data>")));
network.set(BeforeSendUploadDataCallback::class.java,
    BeforeSendUploadDataCallback {  Response.override(TextData.of("<text-data>")) }
)

如果请求没有上传数据,则不会调用此回调。

支持以下 UploadData 类型:

  • BytesData 表示一个字节序列。
  • TextDatatext/plain 内容类型的数据。
  • FormDataapplication/x-www-form-urlencoded 内容类型的数据。
  • MultipartFormDatamultipart/form-data 内容类型的数据。

事务开始之前

BeforeStartTransactionCallback 回调在网络事务开始之前被调用。 在此回调中,您可以在发送之前添加或覆盖 HTTP 标头。 例如:

network.set(BeforeStartTransactionCallback.class, (params) -> {
    List<HttpHeader> httpHeaders = new ArrayList<>(params.httpHeaders());
    httpHeaders.add(HttpHeader.of("<header-name>", "<header-value>"));
    return Response.override(httpHeaders);
});
network.set(BeforeStartTransactionCallback::class.java,
    BeforeStartTransactionCallback { params ->
        val httpHeaders = buildList<HttpHeader> {
            addAll(params.httpHeaders())
            add(HttpHeader.of("<header-name>", "<header-value>"))
        }
        Response.override(httpHeaders)
    }
)

当前未向回调提供以下标头。 此列表不保证是完整或稳定的:

- Authorization
- Cache-Control
- Connection
- Content-Length
- Host
- If-Modified-Since
- If-None-Match
- If-Range
- Partial-Data
- Pragma
- Proxy-Authorization
- Proxy-Connection
- Transfer-Encoding

接收标头

ReceiveHeadersCallback 回调是在 HTTP 请求收到标头时调用的。 您可以在此处添加、修改或删除通过网络接收的 HTTP 标头。 例如:

network.set(ReceiveHeadersCallback.class, (params) -> {
    List<HttpHeader> httpHeaders = new ArrayList<>(params.httpHeaders());
    httpHeaders.add(HttpHeader.of("<header-name>", "<header-value>"));
    return Response.override(httpHeaders);
});
network.set(ReceiveHeadersCallback::class.java,
    ReceiveHeadersCallback { params ->
        val httpHeaders = buildList<HttpHeader> {
            addAll(params.httpHeaders())
            add(HttpHeader.of("<header-name>", "<header-value>"))
        }
        Response.override(httpHeaders)
    }
)

收到重定向响应代码

当收到请求的重定向响应代码 3xx 时,将触发 RedirectResponseCodeReceived 事件。 在这种情况下,您可以获得有关重定向的详细信息,例如新 URL 和响应代码。 例如:

network.on(RedirectResponseCodeReceived.class, (event) -> {
    String newUrl = event.newUrl();
    int responseCode = event.responseCode();
});
network.on(RedirectResponseCodeReceived::class.java) { event -> 
    val newUrl = event.newUrl()
    val responseCode = event.responseCode()
}

响应开始

ResponseStarted 事件在收到 URL 响应正文的第一个字节时触发。 对于 HTTP 请求,这意味着状态行和响应标头是可用的。 在这种情况下,您可以访问相应的请求和响应代码。 例如:

network.on(ResponseStarted.class, (event) -> {
    UrlRequest urlRequest = event.urlRequest();
    int responseCode = event.responseCode();
});
network.on(ResponseStarted::class.java) { event -> 
    val urlRequest = event.urlRequest()
    val responseCode = event.responseCode()
}

请求完成

当 URL 请求成功完成或失败时,将触发 RequestCompleted 事件。 在此事件中,您可以检查请求是否已经开始,获取请求状态的详细信息,访问响应代码。 例如:

network.on(RequestCompleted.class, (event) -> {
    UrlRequest urlRequest = event.urlRequest();
    // The details of the URL request state.
    UrlRequestStatus urlRequestStatus = event.status();
    // The HTTP response code.
    int responseCode = event.responseCode();
});
network.on(RequestCompleted::class.java) { event -> 
    val urlRequest = event.urlRequest()
    // The details of the URL request state.
    val urlRequestStatus = event.status()
    // The HTTP response code.
    val responseCode = event.responseCode()
}

请求销毁

RequestDestroyed 事件是在请求被销毁并且不能再使用时触发的。 要访问已销毁请求的详细信息,请使用以下代码:

network.on(RequestDestroyed.class, (event) -> {
    UrlRequest urlRequest = event.urlRequest();
});
network.on(RequestDestroyed::class.java) { event -> 
    val urlRequest = event.urlRequest()
}

接收到的响应字节

ResponseBytesReceived 事件在通过网络接收到 HTTP 响应正文的一部分时触发。 它允许访问 HTTP 响应主体的字节:

network.on(ResponseBytesReceived.class, event -> {
    byte[] data = event.data();
});
network.on(ResponseBytesReceived::class.java) { event ->
    val data = event.data()
}

连接状态

Chromium 在内部跟踪互联网连接状态。 当网络连接断开然后恢复时,Chromium 会检测到这一点并以编程方式重新加载当前加载的网页。 您可以使用以下 API 在网络连接状态更改时获得通知:

network.on(NetworkChanged.class, e -> {
    // If the connection type is TYPE_NONE, there is no connection.
    if (e.connectionType() == ConnectionType.TYPE_NONE) {
        // The network connection has been dropped. We are offline.
    } else {
        // The network connection has been restored.
    }
});
network.on(NetworkChanged::class.java) { e ->
    // If the connection type is TYPE_NONE, there is no connection.
    if (e.connectionType() == ConnectionType.TYPE_NONE) {
        // The network connection has been dropped. We are offline.
    } else {
        // The network connection has been restored.
    }
}
Go Top