Introdução
Instalação
Guias
- Engine
- Profile
- Browser
- BrowserView
- Navegação
- Conteúdo
- DOM
- JavaScript
- Pop-ups
- Diálogos
- Downloads
- Extensões
- Rede
- Cache
- Cookies
- Proxy
- Autenticação
- Plugins
- Impressão
- Senhas
- Perfis de dados do Usuário
- Cartões de Crédito
- Mídia
- Área de transferência
- Zoom
- Corretor Ortográfico
- Implantação
- Chromium
Resolução de Problemas
Rede
Este guia mostra como trabalhar com a funcionalidade relacionada com a rede, como proxy, eventos de rede, autenticação, TLS, autenticação de certificado de cliente, etc.
A funcionalidade relacionada com a rede pode ser acessada através da instância Network
que pode ser obtida da seguinte forma:
var network = profile.network();
val network = profile.network()
Cabeçalho Accept-Language
O JxBrowser permite configurar o valor do cabeçalho HTTP Accept-Language
através do método Network.acceptLanguage(String)
.
Por exemplo, o valor “fr, en-gb;q=0.8, en;q=0.7” significaria: “Prefiro francês, mas aceito inglês britânico e outros tipos de inglês”:
network.acceptLanguage("fr, en-gb;q=0.8, en;q=0.7");
network.acceptLanguage("fr, en-gb;q=0.8, en;q=0.7")
Servidores Whitelist
Whitelist de Autorização do Servidor HTTP
Você pode configurar a lista branca de autorização do servidor HTTP que representa uma string com uma lista de URLs separados por vírgula/semicoluna. Por exemplo:
network.httpAuthPreferences().serverWhitelist("*google.com,*example.com,*baz");
network.httpAuthPreferences()
.serverWhitelist("*google.com,*example.com,*baz")
Whitelist de Delegados de Rede HTTP
Para configurar a lista branca de delegados de rede HTTP, você pode utilizar a abordagem descrita abaixo:
network.httpAuthPreferences().delegateWhitelist("*google.com,*example.com,*baz");
network.httpAuthPreferences()
.delegateWhitelist("*google.com,*example.com,*baz")
TLS
Verificação do Certificado
Por padrão, o Chromium verifica todos os certificados SSL obtidos de um servidor Web durante o carregamento da página Web. O JxBrowser permite modificar este comportamento padrão e assumir o controle do processo de verificação.
Para lidar com a verificação de certificados, utilize a chamada de retorno VerifyCertificateCallback
. Antes de esta chamada de retorno ser invocada, o Chromium verifica o certificado SSL e fornece os resultados da verificação à chamada de retorno. Com os resultados da verificação, a chamada de retorno recebe o próprio certificado SSL. É possível verificar o certificado SSL fornecido e notificar o motor com os resultados da verificação.
Por exemplo:
network.set(VerifyCertificateCallback.class, (params) -> {
// Certificado SSL a verificar.
var certificate = params.certificate();
// Os resultados da verificação efetuada pelo verificador padrão.
var verificationErrors = params.verificationErrors();
// Devem ser utilizados os resultados da verificação padrão.
return VerifyCertificateCallback.Response.defaultAction();
});
network.register(VerifyCertificateCallback { params ->
// Certificado SSL a verificar.
val certificate = params.certificate()
// Os resultados da verificação efetuada pelo verificador padrão.
val verificationErrors = params.verificationErrors()
// Devem ser utilizados os resultados da verificação padrão.
VerifyCertificateCallback.Response.defaultAction()
})
Autenticação do Certificado do Cliente
O JxBrowser suporta a autenticação utilizando certificados de cliente HTTPS. Para mais informações, consulte o guia Autenticação.
Esquemas
A biblioteca fornece uma API que permite registrar os esquemas personalizados e interceptar requests URL com os esquemas padrão, como HTTP ou HTTPS.
Em ambos os casos, os requests de URL com o esquema correspondente serão interceptados e os dados de resposta serão fornecidos como se fossem enviados por um servidor Web. Utilizando esta funcionalidade, é possível emular a resposta de um servidor remoto e utilizar uma espécie de servidor Web local.
Registrar um Esquema Personalizado
Para registrar um esquema personalizado utilize o método EngineOptions.Builder.addScheme()
durante a configuração do Engine
. Isso é necessário porque o Chromium registra todos os esquemas durante o inicialização e não permite a modificação de esquemas depois de ter sido inicializado.
O código a seguir demonstra como registrar um esquema personalizado e associar a chamada de retorno InterceptUrlRequestCallback
que será invocada sempre que o navegador carregar um recurso por um URL com o esquema fornecido:
InterceptUrlRequestCallback interceptor = params -> {
var options = UrlRequestJob.Options.newBuilder(HttpStatus.OK)
.addHttpHeader(HttpHeader.of("Content-Type", "text/plain"))
.build();
var job = params.newUrlRequestJob(options);
job.write("Hello!".getBytes());
job.complete();
return InterceptUrlRequestCallback.Response.intercept(job);
};
var options = EngineOptions.newBuilder(renderingMode)
.addScheme(Scheme.of("jxb"), interceptor)
.build();
var engine = Engine.newInstance(options);
val interceptor = InterceptUrlRequestCallback { params ->
val options = UrlRequestJobOptions(
status = HttpStatus.OK,
headers = listOf(HttpHeader("Content-Type", "text/plain"))
)
val job = params.newUrlRequestJob(options).apply {
write("Hello!".toByteArray())
complete()
}
InterceptUrlRequestCallback.Response.intercept(job)
}
val engine = Engine(renderingMode) {
schemes.add(Scheme("jxb"), interceptor)
}
Agora, se você carregar jxb://anyhost/anypage.html
, os requests de URL serão interceptados e a chamada de retorno associada será invocada. Você obterá o seguinte resultado:
Interceptação de Requests HTTP/HTTPS
A mesma abordagem com o registro de um esquema personalizado pode ser utilizada para interceptar os esquemas padrão, como HTTP ou HTTPS. Neste caso, é necessário adicionar o esquema correspondente, como indicado abaixo:
InterceptUrlRequestCallback interceptor = params -> {
var jobOptions = UrlRequestJob.Options.newBuilder(HttpStatus.OK)
.addHttpHeader(HttpHeader.of("Content-Type", "text/plain"))
.build();
var job = params.newUrlRequestJob(jobOptions);
...
return InterceptUrlRequestCallback.Response.intercept(job);
};
var options = EngineOptions.newBuilder(renderingMode)
.addScheme(Scheme.HTTPS, interceptor)
.build();
val interceptor = InterceptUrlRequestCallback { params ->
val options = UrlRequestJobOptions(
status = HttpStatus.OK,
headers = listOf(HttpHeader("Content-Type", "text/plain"))
)
val job = params.newUrlRequestJob(options)
...
InterceptUrlRequestCallback.Response.intercept(job)
}
val engine = Engine(renderingMode) {
schemes.add(Scheme.HTTPS, interceptor)
}
Eventos de Rede e Chamadas de Retorno
A API Network
define um conjunto de eventos e chamadas de retorno que seguem o ciclo de vida de um request Web. Você pode utilizar estes eventos para observar e analisar o tráfego. As chamadas de retorno lhe permitirão interceptar, bloquear ou modificar requests.
O ciclo de vida dos eventos de requests bem sucedidos é o seguinte:
Antes do Request de URL
A chamada de retorno BeforeUrlRequestCallback
é invocada quando uma solicitação HTTP está prestes a ocorrer. Você pode utilizar esta chamada de retorno para redirecionar o request para outra localização. Por exemplo:
network.set(BeforeUrlRequestCallback.class, (params) ->
BeforeUrlRequestCallback.Response.redirect("<new-url>"));
network.register(BeforeUrlRequestCallback {
BeforeUrlRequestCallback.Response.redirect("<new-url>")
})
Antes do Upload de Dados
A chamada de retorno BeforeSendUploadDataCallback
é invocada antes dos dados de upload serem enviados para um servidor Web. Aqui você pode sobrescrever os dados de upload. Por exemplo:
network.set(BeforeSendUploadDataCallback.class, (params) ->
BeforeSendUploadDataCallback.Response.override(TextData.of("<text-data>")));
network.register(BeforeSendUploadDataCallback {
val newData = TextData("<text-data>")
BeforeSendUploadDataCallback.Response.override(newData)
})
Esta chamada de retorno não será chamada se o request não tiver os dados de upload.
São suportados os seguintes tipos de UploadData
:
BytesData
representa uma sequência de bytes, o tipo de conteúdo é configurável.TextData
os dados do tipo de conteúdotext/plain
.FormData
os dados do tipo de conteúdoapplication/x-www-form-urlencoded
.MultipartFormData
os dados do tipo de conteúdomultipart/form-data
.
Antes de Iniciar a Transação
A chamada de retorno BeforeStartTransactionCallback
é invocada antes do início da transação de rede. Nesta chamada de retorno, você pode
adicionar ou substituir os cabeçalhos HTTP antes de serem enviados. Por exemplo:
network.set(BeforeStartTransactionCallback.class, (params) -> {
var httpHeaders = new ArrayList<>(params.httpHeaders());
httpHeaders.add(HttpHeader.of("<header-name>", "<header-value>"));
return BeforeStartTransactionCallback.Response.override(httpHeaders);
});
network.register(BeforeStartTransactionCallback { params ->
val customHeader = HttpHeader("<header-name>", "<header-value>")
val httpHeaders = params.httpHeaders() + customHeader
BeforeStartTransactionCallback.Response.override(httpHeaders)
})
Esta chamada de retorno não capta os seguintes cabeçalhos. Esta lista está sujeita a alterações e pode não estar completa:
- Authorization
- Cache-Control
- Connection
- Content-Length
- Host
- If-Modified-Since
- If-None-Match
- If-Range
- Partial-Data
- Pragma
- Proxy-Authorization
- Proxy-Connection
- Transfer-Encoding
Receber Cabeçalhos
A chamada de retorno ReceiveHeadersCallback
é invocada para requests HTTP quando os cabeçalhos são recebidos. Aqui você pode adicionar, modificar ou remover os cabeçalhos HTTP recebidos através da rede. Por exemplo:
network.set(ReceiveHeadersCallback.class, (params) -> {
var httpHeaders = new ArrayList<>(params.httpHeaders());
httpHeaders.add(HttpHeader.of("<header-name>", "<header-value>"));
return ReceiveHeadersCallback.Response.override(httpHeaders);
});
network.register(ReceiveHeadersCallback { params ->
val customHeader = HttpHeader("<header-name>", "<header-value>")
val httpHeaders = params.httpHeaders() + customHeader
ReceiveHeadersCallback.Response.override(httpHeaders)
})
Código de Resposta de Redirecionamento Recebido
O evento RedirectResponseCodeReceived
é disparado quando um código de resposta de redirecionamento 3xx
é recebido para o request. Neste evento, você pode obter os detalhes sobre o redirecionamento, como o novo URL e o código de resposta. Por exemplo:
network.on(RedirectResponseCodeReceived.class, (event) -> {
var newUrl = event.newUrl();
var responseCode = event.responseCode();
});
network.subscribe<RedirectResponseCodeReceived> { event ->
val newUrl = event.newUrl()
val responseCode = event.responseCode()
}
Resposta Iniciada
O evento ResponseStarted
é disparado quando o primeiro byte do corpo da resposta do URL é recebido. Para os pedidos HTTP, isto significa que a linha de estado e os cabeçalhos de resposta estão disponíveis. Neste evento, é possível acessar o request correspondente e o código de resposta. Por exemplo:
network.on(ResponseStarted.class, (event) -> {
var urlRequest = event.urlRequest();
var responseCode = event.responseCode();
});
network.subscribe<ResponseStarted> { event ->
val urlRequest = event.urlRequest()
val responseCode = event.responseCode()
}
Request Concluído
O evento RequestCompleted
é disparado quando o request de URL foi concluído com sucesso ou falhou. Neste evento, é possível verificar se o request foi iniciado, obter os detalhes do estado do request e acessar o código de resposta. Por exemplo:
network.on(RequestCompleted.class, (event) -> {
var urlRequest = event.urlRequest();
// Os detalhes do estado do request de URL.
var urlRequestStatus = event.status();
// O código de resposta HTTP.
var responseCode = event.responseCode();
});
network.subscribe<RequestCompleted> { event ->
val urlRequest = event.urlRequest()
// Os detalhes do estado do request de URL.
val urlRequestStatus = event.status()
// O código de resposta HTTP.
val responseCode = event.responseCode()
}
Request Destruído
O evento RequestDestroyed
é disparado quando o request é destruído e não pode mais ser utilizado. Para acessar os detalhes do request destruído, utilize o seguinte código:
network.on(RequestDestroyed.class, (event) -> {
var urlRequest = event.urlRequest();
});
network.subscribe<RequestDestroyed> { event ->
val urlRequest = event.urlRequest()
}
Bytes de Resposta Recebidos
O evento ResponseBytesReceived
é disparado quando uma parte do corpo da resposta HTTP é recebida através
da rede. Ele permite acessar os bytes do corpo da resposta HTTP:
network.on(ResponseBytesReceived.class, event -> {
var data = event.data();
});
network.subscribe<ResponseBytesReceived> { event ->
val data = event.data()
}
As partes do corpo da resposta podem ser apresentadas numa ordem aleatória. Tenha isso em mente ao restaurar a resposta completa usando este evento.
Estado da Conexão
O Chromium monitora o estado da conexão à Internet. Quando a conexão é interrompida e depois restaurada, o Chromium detecta a alteração e volta a carregar a página Web atualmente carregada. Você pode obter as notificações correspondentes utilizando a seguinte API:
network.on(NetworkChanged.class, e -> {
// Se o tipo de conexão for TYPE_NONE, não existe qualquer conexão.
if (e.connectionType() == ConnectionType.TYPE_NONE) {
// A conexão de rede foi interrompida. Estamos offline.
} else {
// A conexão de rede foi restabelecida.
}
});
network.subscribe<NetworkChanged> { event ->
// Se o tipo de conexão for TYPE_NONE, não existe qualquer conexão.
if (event.connectionType() == ConnectionType.TYPE_NONE) {
// A conexão de rede foi interrompida. Estamos offline.
} else {
// A conexão de rede foi restabelecida.
}
}