diff --git a/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java b/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java index 61e5db5ca9c3..471da19667f8 100644 --- a/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java +++ b/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java @@ -40,6 +40,11 @@ import java.util.List; public class BuiltInWebBrowserUrlProvider extends WebBrowserUrlProvider implements DumbAware { @NotNull public static List getUrls(@NotNull VirtualFile file, @NotNull Project project, @Nullable String currentAuthority) { + return getUrls(file, project, currentAuthority, true); + } + + @NotNull + public static List getUrls(@NotNull VirtualFile file, @NotNull Project project, @Nullable String currentAuthority, boolean appendAccessToken) { if (currentAuthority != null && !compareAuthority(currentAuthority)) { return Collections.emptyList(); } @@ -53,7 +58,7 @@ public class BuiltInWebBrowserUrlProvider extends WebBrowserUrlProvider implemen String path = info.getPath(); String authority = currentAuthority == null ? "localhost:" + effectiveBuiltInServerPort : currentAuthority; - String query = "?" + BuiltInWebServerKt.TOKEN_PARAM_NAME + "=" + BuiltInWebServerKt.acquireToken(); + String query = appendAccessToken ? "?" + BuiltInWebServerKt.TOKEN_PARAM_NAME + "=" + BuiltInWebServerKt.acquireToken() : ""; List urls = new SmartList<>(Urls.newHttpUrl(authority, '/' + project.getName() + '/' + path, query)); String path2 = info.getRootLessPathIfPossible(); @@ -118,7 +123,7 @@ public class BuiltInWebBrowserUrlProvider extends WebBrowserUrlProvider implemen return Urls.newFromVirtualFile(file); } else { - return ContainerUtil.getFirstItem(getUrls(file, request.getProject(), null)); + return ContainerUtil.getFirstItem(getUrls(file, request.getProject(), null, request.isAppendAccessToken())); } } } diff --git a/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebServer.kt b/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebServer.kt index 0f3d9b2a31a3..308937b079c9 100644 --- a/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebServer.kt +++ b/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebServer.kt @@ -108,6 +108,7 @@ class BuiltInWebServer : HttpRequestHandler() { internal fun isActivatable() = Registry.`is`("ide.built.in.web.server.activatable", false) internal const val TOKEN_PARAM_NAME = "_ijt" +const val TOKEN_HEADER_NAME = "x-ijt" private val STANDARD_COOKIE by lazy { val productName = ApplicationNamesInfo.getInstance().lowercaseProductName @@ -139,7 +140,7 @@ private val STANDARD_COOKIE by lazy { // expire after access because we reuse tokens private val tokens = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.MINUTES).build() -internal fun acquireToken(): String { +fun acquireToken(): String { var token = tokens.asMap().keys.firstOrNull() if (token == null) { token = TokenGenerator.generate() @@ -252,7 +253,9 @@ internal fun validateToken(request: HttpRequest, channel: Channel): HttpHeaders? val urlDecoder = QueryStringDecoder(request.uri()) // we must check referrer - if html cached, browser will send request without query - val token = urlDecoder.parameters().get(TOKEN_PARAM_NAME)?.firstOrNull() ?: request.referrer?.let { QueryStringDecoder(it).parameters().get(TOKEN_PARAM_NAME)?.firstOrNull() } + val token = request.headers().get(TOKEN_HEADER_NAME) + ?: urlDecoder.parameters().get(TOKEN_PARAM_NAME)?.firstOrNull() + ?: request.referrer?.let { QueryStringDecoder(it).parameters().get(TOKEN_PARAM_NAME)?.firstOrNull() } val url = "${channel.uriScheme}://${request.host!!}${urlDecoder.path()}" if (token != null && tokens.getIfPresent(token) != null) { tokens.invalidate(token) diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.kt b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.kt index d8c1914c8e39..b760cddf1561 100644 --- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.kt +++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.kt @@ -24,7 +24,7 @@ import io.netty.handler.codec.http.QueryStringDecoder internal abstract class DelegatingHttpRequestHandlerBase : SimpleChannelInboundHandlerAdapter() { override fun messageReceived(context: ChannelHandlerContext, message: FullHttpRequest) { - Logger.getInstance(BuiltInServer::class.java).debug { "IN HTTP: $message" } + Logger.getInstance(BuiltInServer::class.java).debug { "\n\nIN HTTP: $message\n\n" } if (!process(context, message, QueryStringDecoder(message.uri()))) { HttpResponseStatus.NOT_FOUND.send(context.channel(), message) diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java index be5151bb06a5..9f23e779ed19 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -94,7 +94,14 @@ public class WebBrowserServiceImpl extends WebBrowserService { public static Collection getDebuggableUrls(@Nullable PsiElement context) { try { OpenInBrowserRequest request = context == null ? null : OpenInBrowserRequest.create(context); - return request == null || request.getFile().getViewProvider().getBaseLanguage() == XMLLanguage.INSTANCE ? Collections.emptyList() : getUrls(getProvider(request), request); + if (request == null || request.getFile().getViewProvider().getBaseLanguage() == XMLLanguage.INSTANCE) { + return Collections.emptyList(); + } + else { + // it is client responsibility to set token + request.setAppendAccessToken(false); + return getUrls(getProvider(request), request); + } } catch (WebBrowserUrlProvider.BrowserException ignored) { return Collections.emptyList(); diff --git a/xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java b/xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java index c4119d10c8c0..3f8d70e8522d 100644 --- a/xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java +++ b/xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.ide.browsers; import com.intellij.openapi.application.AccessToken; @@ -15,6 +30,8 @@ import java.util.Collection; public abstract class OpenInBrowserRequest { private Collection result; protected PsiFile file; + + private boolean appendAccessToken = true; public OpenInBrowserRequest(@NotNull PsiFile file) { this.file = file; @@ -72,4 +89,12 @@ public abstract class OpenInBrowserRequest { public Collection getResult() { return result; } + + public boolean isAppendAccessToken() { + return appendAccessToken; + } + + public void setAppendAccessToken(boolean value) { + this.appendAccessToken = value; + } } \ No newline at end of file