pass token in the headers in debug mode
authorVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Wed, 27 Apr 2016 10:53:35 +0000 (12:53 +0200)
committerVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Wed, 27 Apr 2016 10:53:35 +0000 (12:53 +0200)
platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java
platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebServer.kt
platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.kt
xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java

index 61e5db5ca9c36b004c78885fda95dc576a559bb0..471da19667f816050521eb5664245b2b581eb06a 100644 (file)
@@ -40,6 +40,11 @@ import java.util.List;
 public class BuiltInWebBrowserUrlProvider extends WebBrowserUrlProvider implements DumbAware {
   @NotNull
   public static List<Url> getUrls(@NotNull VirtualFile file, @NotNull Project project, @Nullable String currentAuthority) {
+    return getUrls(file, project, currentAuthority, true);
+  }
+  
+  @NotNull
+  public static List<Url> 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<Url> 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()));
     }
   }
 }
index 0f3d9b2a31a3684e1389792c4a71753e67cb59c3..308937b079c9084353aa2e3ddcaceedfd79f239b 100644 (file)
@@ -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<String, Boolean>()
 
-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)
index d8c1914c8e398bf4bf29ba80345bdda879a6c959..b760cddf15617f62c12d09b9bcd90fb0575ef736 100644 (file)
@@ -24,7 +24,7 @@ import io.netty.handler.codec.http.QueryStringDecoder
 
 internal abstract class DelegatingHttpRequestHandlerBase : SimpleChannelInboundHandlerAdapter<FullHttpRequest>() {
   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)
index be5151bb06a50825a579d340a9ffa7ba616a624e..9f23e779ed1931f33cc73d7dd92dc007ce81a828 100644 (file)
@@ -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<Url> getDebuggableUrls(@Nullable PsiElement context) {
     try {
       OpenInBrowserRequest request = context == null ? null : OpenInBrowserRequest.create(context);
-      return request == null || request.getFile().getViewProvider().getBaseLanguage() == XMLLanguage.INSTANCE ? Collections.<Url>emptyList() : getUrls(getProvider(request), request);
+      if (request == null || request.getFile().getViewProvider().getBaseLanguage() == XMLLanguage.INSTANCE) {
+        return Collections.<Url>emptyList();
+      }
+      else {
+        // it is client responsibility to set token
+        request.setAppendAccessToken(false);
+        return getUrls(getProvider(request), request);
+      }
     }
     catch (WebBrowserUrlProvider.BrowserException ignored) {
       return Collections.emptyList();
index c4119d10c8c09079d728e91c1d175dfecf211a57..3f8d70e8522d059e6c14a92233133ac589aef115 100644 (file)
@@ -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<Url> 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<Url> getResult() {
     return result;
   }
+
+  public boolean isAppendAccessToken() {
+    return appendAccessToken;
+  }
+
+  public void setAppendAccessToken(boolean value) {
+    this.appendAccessToken = value;
+  }
 }
\ No newline at end of file