티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

Add custom headers to WebView resource requests - android

WebView 리소스 요청에 사용자 지정 헤더를 추가해야합니다 - 안드로이드

 문제 내용 

I need to add custom headers to EVERY request coming from the WebView. I know loadURL has the parameter for extraHeaders, but those are only applied to the initial request. All subsequent requests do not contain the headers. I have looked at all overrides in WebViewClient, but nothing allows for adding headers to resource requests - onLoadResource(WebView view, String url). Any help would be wonderful.

WebView에서 온 모든 요청에 사용자 지정 헤더를 추가해야합니다. loadURL에는 extraHeaders 매개 변수가 있지만 이는 초기 요청에만 적용됩니다. 모든 후속 요청에는 헤더가 포함되지 않습니다. WebViewClient에서 모든 오버라이드를 살펴보았지만, onLoadResource (WebView view, String url)를 사용하여 리소스 요청에 헤더를 추가하는 방법은 없습니다. 도움이 필요합니다.

 

Thanks, Ray

감사합니다, Ray

 

 

 

 높은 점수를 받은 Solution 

Try

해결 방법:
loadUrl(String url, Map<String, String> extraHeaders)

 

For adding headers to resources loading requests, make custom WebViewClient and override:

리소스 로딩 요청에 헤더를 추가하려면 사용자 지정 WebViewClient를 만들고 다음을 재정의하세요.
API 24+:
WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
or
WebResourceResponse shouldInterceptRequest(WebView view, String url)

 

 

 가장 최근 달린 Solution 

Here is an implementation using HttpUrlConnection:

HttpUrlConnection을 사용하는 구현 방법은 다음과 같습니다.
class CustomWebviewClient : WebViewClient() {
    private val charsetPattern = Pattern.compile(".*?charset=(.*?)(;.*)?$")

    override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
        try {
            val connection: HttpURLConnection = URL(request.url.toString()).openConnection() as HttpURLConnection
            connection.requestMethod = request.method
            for ((key, value) in request.requestHeaders) {
                connection.addRequestProperty(key, value)
            }

            connection.addRequestProperty("custom header key", "custom header value")

            var contentType: String? = connection.contentType
            var charset: String? = null
            if (contentType != null) {
                // some content types may include charset => strip; e. g. "application/json; charset=utf-8"
                val contentTypeTokenizer = StringTokenizer(contentType, ";")
                val tokenizedContentType = contentTypeTokenizer.nextToken()

                var capturedCharset: String? = connection.contentEncoding
                if (capturedCharset == null) {
                    val charsetMatcher = charsetPattern.matcher(contentType)
                    if (charsetMatcher.find() && charsetMatcher.groupCount() > 0) {
                        capturedCharset = charsetMatcher.group(1)
                    }
                }
                if (capturedCharset != null && !capturedCharset.isEmpty()) {
                    charset = capturedCharset
                }

                contentType = tokenizedContentType
            }

            val status = connection.responseCode
            var inputStream = if (status == HttpURLConnection.HTTP_OK) {
                connection.inputStream
            } else {
                // error stream can sometimes be null even if status is different from HTTP_OK
                // (e. g. in case of 404)
                connection.errorStream ?: connection.inputStream
            }
            val headers = connection.headerFields
            val contentEncodings = headers.get("Content-Encoding")
            if (contentEncodings != null) {
                for (header in contentEncodings) {
                    if (header.equals("gzip", true)) {
                        inputStream = GZIPInputStream(inputStream)
                        break
                    }
                }
            }
            return WebResourceResponse(contentType, charset, status, connection.responseMessage, convertConnectionResponseToSingleValueMap(connection.headerFields), inputStream)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return super.shouldInterceptRequest(view, request)
    }

    private fun convertConnectionResponseToSingleValueMap(headerFields: Map<String, List<String>>): Map<String, String> {
        val headers = HashMap<String, String>()
        for ((key, value) in headerFields) {
            when {
                value.size == 1 -> headers[key] = value[0]
                value.isEmpty() -> headers[key] = ""
                else -> {
                    val builder = StringBuilder(value[0])
                    val separator = "; "
                    for (i in 1 until value.size) {
                        builder.append(separator)
                        builder.append(value[i])
                    }
                    headers[key] = builder.toString()
                }
            }
        }
        return headers
    }
}

 

Note that this does not work for POST requests because WebResourceRequest doesn't provide POST data. There is a Request Data - WebViewClient library which uses a JavaScript injection workaround for intercepting POST data.

POST 요청에는 작동하지 않음에 유의하십시오. WebResourceRequest는 POST 데이터를 제공하지 않습니다. POST 데이터를 가로채기 위한 자바스크립트 주입 해결책을 사용하는 Request Data - WebViewClient 라이브러리가 있습니다.

 

 

 

출처 : https://stackoverflow.com/questions/7610790/add-custom-headers-to-webview-resource-requests-android

반응형
댓글
공지사항
최근에 올라온 글