Skip to content

Commit 51ae37a

Browse files
committed
Gzip response handling (#427)
1 parent 90a8e72 commit 51ae37a

File tree

3 files changed

+118
-101
lines changed

3 files changed

+118
-101
lines changed

src/main/com/intellij/lang/jsgraphql/ide/editor/GraphQLIntrospectionService.java

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,20 @@
6161
import graphql.schema.GraphQLSchema;
6262
import graphql.schema.idl.*;
6363
import graphql.util.EscapeUtil;
64-
import org.apache.commons.httpclient.HttpClient;
65-
import org.apache.commons.httpclient.methods.PostMethod;
66-
import org.apache.commons.httpclient.methods.StringRequestEntity;
67-
import org.apache.commons.httpclient.params.HttpClientParams;
6864
import org.apache.commons.lang.StringEscapeUtils;
6965
import org.apache.commons.lang.StringUtils;
66+
import org.apache.http.client.methods.CloseableHttpResponse;
67+
import org.apache.http.client.methods.HttpPost;
68+
import org.apache.http.client.methods.HttpUriRequest;
69+
import org.apache.http.entity.ContentType;
70+
import org.apache.http.entity.StringEntity;
71+
import org.apache.http.impl.client.CloseableHttpClient;
72+
import org.apache.http.impl.client.HttpClients;
73+
import org.apache.http.util.EntityUtils;
7074
import org.jetbrains.annotations.NotNull;
7175
import org.jetbrains.annotations.Nullable;
7276

7377
import java.io.IOException;
74-
import java.io.UnsupportedEncodingException;
7578
import java.util.Collection;
7679
import java.util.List;
7780
import java.util.Map;
@@ -143,18 +146,24 @@ public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification noti
143146
}
144147

145148
final String requestJson = "{\"query\":\"" + StringEscapeUtils.escapeJavaScript(query) + "\"}";
146-
147-
final PostMethod method = new PostMethod(url);
148-
method.setRequestEntity(new StringRequestEntity(requestJson, "application/json", "UTF-8"));
149-
setHeadersFromOptions(endpoint, method);
150-
151-
Task.Backgroundable task = new IntrospectionQueryTask(method, schemaPath, introspectionSourceFile, retry, graphQLSettings, endpoint, url);
149+
HttpPost request = createRequest(endpoint, url, requestJson);
150+
Task.Backgroundable task = new IntrospectionQueryTask(request, schemaPath, introspectionSourceFile, retry, graphQLSettings, endpoint, url);
152151
ProgressManager.getInstance().run(task);
153-
} catch (UnsupportedEncodingException | IllegalStateException | IllegalArgumentException e) {
154-
GraphQLNotificationUtil.showGraphQLRequestErrorNotification(retry, url, e, NotificationType.ERROR, myProject);
152+
} catch (IllegalStateException | IllegalArgumentException e) {
153+
GraphQLNotificationUtil.showGraphQLRequestErrorNotification(myProject, url, e, NotificationType.ERROR, retry);
155154
}
156155
}
157156

157+
@NotNull
158+
public static HttpPost createRequest(@NotNull GraphQLConfigVariableAwareEndpoint endpoint,
159+
@NotNull String url,
160+
@NotNull String requestJson) {
161+
HttpPost request = new HttpPost(url);
162+
request.setEntity(new StringEntity(requestJson, ContentType.APPLICATION_JSON));
163+
setHeadersFromOptions(endpoint, request);
164+
return request;
165+
}
166+
158167
public void addIntrospectionStackTraceAction(@NotNull Notification notification, @NotNull Exception exception) {
159168
notification.addAction(new NotificationAction(GraphQLBundle.message("graphql.notification.stack.trace")) {
160169
@Override
@@ -418,23 +427,23 @@ public void dispose() {
418427
}
419428

420429
private class IntrospectionQueryTask extends Task.Backgroundable {
421-
private final PostMethod method;
430+
private final HttpUriRequest request;
422431
private final String schemaPath;
423432
private final VirtualFile introspectionSourceFile;
424433
private final NotificationAction retry;
425434
private final GraphQLSettings graphQLSettings;
426435
private final GraphQLConfigVariableAwareEndpoint endpoint;
427436
private final String url;
428437

429-
public IntrospectionQueryTask(@NotNull PostMethod method,
438+
public IntrospectionQueryTask(@NotNull HttpUriRequest request,
430439
@NotNull String schemaPath,
431440
@NotNull VirtualFile introspectionSourceFile,
432441
@NotNull NotificationAction retry,
433442
@NotNull GraphQLSettings graphQLSettings,
434443
@NotNull GraphQLConfigVariableAwareEndpoint endpoint,
435444
@NotNull String url) {
436445
super(GraphQLIntrospectionService.this.myProject, GraphQLBundle.message("graphql.progress.executing.introspection.query"), false);
437-
this.method = method;
446+
this.request = request;
438447
this.schemaPath = schemaPath;
439448
this.introspectionSourceFile = introspectionSourceFile;
440449
this.retry = retry;
@@ -448,12 +457,11 @@ public void run(@NotNull ProgressIndicator indicator) {
448457
indicator.setIndeterminate(true);
449458
String responseJson;
450459

451-
try {
452-
HttpClient httpClient = new HttpClient(new HttpClientParams());
453-
httpClient.executeMethod(method);
454-
responseJson = ObjectUtils.coalesce(method.getResponseBodyAsString(), "");
460+
try (final CloseableHttpClient httpClient = HttpClients.createDefault();
461+
final CloseableHttpResponse response = httpClient.execute(request)) {
462+
responseJson = ObjectUtils.coalesce(EntityUtils.toString(response.getEntity()), "");
455463
} catch (IOException e) {
456-
GraphQLNotificationUtil.showGraphQLRequestErrorNotification(retry, url, e, NotificationType.WARNING, myProject);
464+
GraphQLNotificationUtil.showGraphQLRequestErrorNotification(myProject, url, e, NotificationType.WARNING, retry);
457465
return;
458466
}
459467

src/main/com/intellij/lang/jsgraphql/ide/notifications/GraphQLNotificationUtil.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,21 @@ public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification noti
4242
Notifications.Bus.notify(notification);
4343
}
4444

45-
public static void showGraphQLRequestErrorNotification(@NotNull NotificationAction retry,
45+
public static void showGraphQLRequestErrorNotification(@NotNull Project project,
4646
@NotNull String url,
4747
@NotNull Exception error,
4848
@NotNull NotificationType notificationType,
49-
@NotNull Project project) {
49+
@Nullable NotificationAction retry) {
5050
Notification notification = new Notification(
5151
NOTIFICATION_GROUP_ID,
5252
GraphQLBundle.message("graphql.notification.error.title"),
5353
url + ": " + GraphQLNotificationUtil.formatExceptionMessage(error),
5454
notificationType
55-
).addAction(retry);
55+
);
56+
57+
if (retry != null) {
58+
notification.addAction(retry);
59+
}
5660

5761
Notifications.Bus.notify(notification, project);
5862
}

src/main/com/intellij/lang/jsgraphql/v1/ide/project/JSGraphQLLanguageUIProjectService.java

Lines changed: 82 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import com.intellij.lang.jsgraphql.GraphQLParserDefinition;
2020
import com.intellij.lang.jsgraphql.icons.JSGraphQLIcons;
2121
import com.intellij.lang.jsgraphql.ide.actions.GraphQLEditConfigAction;
22+
import com.intellij.lang.jsgraphql.ide.editor.GraphQLIntrospectionService;
23+
import com.intellij.lang.jsgraphql.ide.notifications.GraphQLNotificationUtil;
2224
import com.intellij.lang.jsgraphql.ide.project.graphqlconfig.GraphQLConfigManager;
2325
import com.intellij.lang.jsgraphql.ide.project.graphqlconfig.model.GraphQLConfigEndpoint;
2426
import com.intellij.lang.jsgraphql.ide.project.graphqlconfig.model.GraphQLConfigVariableAwareEndpoint;
@@ -29,9 +31,7 @@
2931
import com.intellij.lang.jsgraphql.v1.ide.editor.JSGraphQLQueryContextHighlightVisitor;
3032
import com.intellij.lang.jsgraphql.v1.ide.endpoints.JSGraphQLEndpointsModel;
3133
import com.intellij.lang.jsgraphql.v1.ide.project.toolwindow.JSGraphQLLanguageToolWindowManager;
32-
import com.intellij.notification.Notification;
3334
import com.intellij.notification.NotificationType;
34-
import com.intellij.notification.Notifications;
3535
import com.intellij.openapi.Disposable;
3636
import com.intellij.openapi.actionSystem.*;
3737
import com.intellij.openapi.application.ApplicationManager;
@@ -51,6 +51,7 @@
5151
import com.intellij.openapi.ui.ComboBox;
5252
import com.intellij.openapi.util.Disposer;
5353
import com.intellij.openapi.util.Key;
54+
import com.intellij.openapi.util.text.StringUtil;
5455
import com.intellij.openapi.vcs.CodeSmellDetector;
5556
import com.intellij.openapi.vfs.VirtualFile;
5657
import com.intellij.openapi.vfs.VirtualFileManager;
@@ -68,13 +69,15 @@
6869
import com.intellij.util.containers.ContainerUtil;
6970
import com.intellij.util.messages.MessageBusConnection;
7071
import com.intellij.util.ui.UIUtil;
71-
import org.apache.commons.httpclient.Header;
72-
import org.apache.commons.httpclient.HttpClient;
73-
import org.apache.commons.httpclient.methods.PostMethod;
74-
import org.apache.commons.httpclient.methods.StringRequestEntity;
75-
import org.apache.commons.httpclient.params.HttpClientParams;
7672
import org.apache.commons.lang.StringUtils;
7773
import org.apache.commons.lang.time.StopWatch;
74+
import org.apache.http.Header;
75+
import org.apache.http.HttpRequest;
76+
import org.apache.http.client.methods.CloseableHttpResponse;
77+
import org.apache.http.client.methods.HttpPost;
78+
import org.apache.http.impl.client.CloseableHttpClient;
79+
import org.apache.http.impl.client.HttpClients;
80+
import org.apache.http.util.EntityUtils;
7881
import org.jetbrains.annotations.NotNull;
7982

8083
import javax.swing.*;
@@ -83,9 +86,10 @@
8386
import java.awt.event.MouseAdapter;
8487
import java.awt.event.MouseEvent;
8588
import java.io.IOException;
86-
import java.io.UnsupportedEncodingException;
87-
import java.util.*;
89+
import java.util.Collection;
90+
import java.util.HashMap;
8891
import java.util.List;
92+
import java.util.Map;
8993

9094
/**
9195
* Provides the project-specific GraphQL tool window, including errors view, console, and query result editor.
@@ -372,84 +376,85 @@ public void executeGraphQL(Editor editor, VirtualFile virtualFile) {
372376
return;
373377
}
374378
String requestJson = createQueryJsonSerializer().toJson(requestData);
375-
final HttpClientParams params = new HttpClientParams();
376-
params.setContentCharset("UTF-8"); // set fallback charset to align with JSON spec
377-
final HttpClient httpClient = new HttpClient(params);
378379
final String url = endpoint.getUrl();
379380
try {
380-
final PostMethod method = new PostMethod(url);
381-
setHeadersFromOptions(endpoint, method);
382-
method.setRequestEntity(new StringRequestEntity(requestJson, "application/json", "UTF-8"));
383-
384-
final Runnable executeQuery = () -> {
385-
try {
386-
try {
387-
editor.putUserData(JS_GRAPH_QL_EDITOR_QUERYING, true);
388-
StopWatch sw = new StopWatch();
389-
sw.start();
390-
httpClient.executeMethod(method);
391-
final String responseJson = Optional.ofNullable(method.getResponseBodyAsString()).orElse("");
392-
sw.stop();
393-
final Header responseHeader = method.getResponseHeader("Content-Type");
394-
final boolean reformatJson = responseHeader != null && responseHeader.getValue() != null && responseHeader.getValue().startsWith("application/json");
395-
final Integer errorCount = getErrorCount(responseJson);
396-
if (fileEditor instanceof TextEditor) {
397-
final TextEditor textEditor = (TextEditor) fileEditor;
398-
UIUtil.invokeLaterIfNeeded(() -> {
399-
updateQueryResultEditor(responseJson, textEditor, reformatJson);
400-
final StringBuilder queryResultText = new StringBuilder(virtualFile.getName()).
401-
append(": ").
402-
append(sw.getTime()).
403-
append(" ms execution time, ").
404-
append(bytesToDisplayString(responseJson.length())).
405-
append(" response");
406-
407-
if (errorCount != null && errorCount > 0) {
408-
queryResultText.append(", ").append(errorCount).append(" error").append(errorCount > 1 ? "s" : "");
409-
if (context.onError != null) {
410-
context.onError.run();
411-
}
412-
}
413-
414-
queryResultLabel.setText(queryResultText.toString());
415-
queryResultLabel.putClientProperty(FILE_URL_PROPERTY, virtualFile.getUrl());
416-
if (!queryResultLabel.isVisible()) {
417-
queryResultLabel.setVisible(true);
418-
}
419-
420-
querySuccessLabel.setVisible(errorCount != null);
421-
if (querySuccessLabel.isVisible()) {
422-
if (errorCount == 0) {
423-
querySuccessLabel.setBorder(BorderFactory.createEmptyBorder(2, 8, 0, 0));
424-
querySuccessLabel.setIcon(AllIcons.General.InspectionsOK);
425-
} else {
426-
querySuccessLabel.setBorder(BorderFactory.createEmptyBorder(2, 12, 0, 4));
427-
querySuccessLabel.setIcon(AllIcons.Ide.ErrorPoint);
428-
}
429-
}
430-
showQueryResultEditor(textEditor);
431-
});
432-
}
433-
} finally {
434-
editor.putUserData(JS_GRAPH_QL_EDITOR_QUERYING, null);
435-
}
436-
} catch (IOException | IllegalArgumentException e) {
437-
Notifications.Bus.notify(new Notification("GraphQL", "GraphQL Query Error", url + ": " + e.getMessage(), NotificationType.WARNING), myProject);
438-
}
439-
};
381+
final HttpPost request = GraphQLIntrospectionService.createRequest(endpoint, url, requestJson);
440382
final Task.Backgroundable task = new Task.Backgroundable(myProject, "Executing GraphQL", false) {
441383
@Override
442384
public void run(@NotNull ProgressIndicator indicator) {
443385
indicator.setIndeterminate(true);
444-
executeQuery.run();
386+
runQuery(editor, virtualFile, context, url, request);
445387
}
446388
};
447389
ProgressManager.getInstance().run(task);
448-
} catch (UnsupportedEncodingException | IllegalStateException | IllegalArgumentException e) {
449-
Notifications.Bus.notify(new Notification("GraphQL", "GraphQL Query Error", url + ": " + e.getMessage(), NotificationType.ERROR), myProject);
390+
} catch (IllegalStateException | IllegalArgumentException e) {
391+
GraphQLNotificationUtil.showGraphQLRequestErrorNotification(myProject, url, e, NotificationType.ERROR, null);
392+
}
393+
394+
}
395+
}
396+
}
397+
398+
private void runQuery(Editor editor, VirtualFile virtualFile, JSGraphQLQueryContext context, String url, HttpPost request) {
399+
try {
400+
try (final CloseableHttpClient httpClient = HttpClients.createDefault()) {
401+
editor.putUserData(JS_GRAPH_QL_EDITOR_QUERYING, true);
402+
403+
String responseJson;
404+
Header contentType;
405+
StopWatch sw = new StopWatch();
406+
sw.start();
407+
try (final CloseableHttpResponse response = httpClient.execute(request)) {
408+
responseJson = StringUtil.notNullize(EntityUtils.toString(response.getEntity()));
409+
contentType = response.getFirstHeader("Content-Type");
410+
} finally {
411+
sw.stop();
450412
}
451413

414+
final boolean reformatJson = contentType != null && contentType.getValue() != null && contentType.getValue().startsWith("application/json");
415+
final Integer errorCount = getErrorCount(responseJson);
416+
if (fileEditor instanceof TextEditor) {
417+
final TextEditor textEditor = (TextEditor) fileEditor;
418+
UIUtil.invokeLaterIfNeeded(() -> {
419+
updateQueryResultEditor(responseJson, textEditor, reformatJson);
420+
final StringBuilder queryResultText = new StringBuilder(virtualFile.getName()).
421+
append(": ").
422+
append(sw.getTime()).
423+
append(" ms execution time, ").
424+
append(bytesToDisplayString(responseJson.length())).
425+
append(" response");
426+
427+
if (errorCount != null && errorCount > 0) {
428+
queryResultText.append(", ").append(errorCount).append(" error").append(errorCount > 1 ? "s" : "");
429+
if (context.onError != null) {
430+
context.onError.run();
431+
}
432+
}
433+
434+
queryResultLabel.setText(queryResultText.toString());
435+
queryResultLabel.putClientProperty(FILE_URL_PROPERTY, virtualFile.getUrl());
436+
if (!queryResultLabel.isVisible()) {
437+
queryResultLabel.setVisible(true);
438+
}
439+
440+
querySuccessLabel.setVisible(errorCount != null);
441+
if (querySuccessLabel.isVisible()) {
442+
if (errorCount == 0) {
443+
querySuccessLabel.setBorder(BorderFactory.createEmptyBorder(2, 8, 0, 0));
444+
querySuccessLabel.setIcon(AllIcons.General.InspectionsOK);
445+
} else {
446+
querySuccessLabel.setBorder(BorderFactory.createEmptyBorder(2, 12, 0, 4));
447+
querySuccessLabel.setIcon(AllIcons.Ide.ErrorPoint);
448+
}
449+
}
450+
showQueryResultEditor(textEditor);
451+
});
452+
}
453+
} finally {
454+
editor.putUserData(JS_GRAPH_QL_EDITOR_QUERYING, null);
452455
}
456+
} catch (IOException | IllegalArgumentException e) {
457+
GraphQLNotificationUtil.showGraphQLRequestErrorNotification(myProject, url, e, NotificationType.WARNING, null);
453458
}
454459
}
455460

@@ -541,11 +546,11 @@ private static String bytesToDisplayString(long bytes) {
541546
return String.format("%.1f %sb", bytes / Math.pow(1000, exp), pre);
542547
}
543548

544-
public static void setHeadersFromOptions(GraphQLConfigVariableAwareEndpoint endpoint, PostMethod method) {
549+
public static void setHeadersFromOptions(GraphQLConfigVariableAwareEndpoint endpoint, HttpRequest request) {
545550
final Map<String, Object> headers = endpoint.getHeaders();
546551
if (headers != null) {
547552
for (Map.Entry<String, Object> entry : headers.entrySet()) {
548-
method.setRequestHeader(entry.getKey(), String.valueOf(entry.getValue()));
553+
request.setHeader(entry.getKey(), String.valueOf(entry.getValue()));
549554
}
550555
}
551556
}

0 commit comments

Comments
 (0)