Added POSTRequest processing with raw input
This commit is contained in:
parent
4ba67f13aa
commit
115c96a3aa
9 changed files with 372 additions and 32 deletions
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2018 Rohit Awate.
|
||||
*
|
||||
* 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.rohitawate.restaurant.dashboard;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.TextArea;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class BodyTabController implements Initializable {
|
||||
@FXML
|
||||
private ComboBox<String> rawInputTypeBox;
|
||||
@FXML
|
||||
private TextArea rawInputArea;
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
rawInputTypeBox.getItems().addAll("PLAIN TEXT", "JSON", "XML", "HTML");
|
||||
rawInputTypeBox.getSelectionModel().select(0);
|
||||
}
|
||||
|
||||
// Returns the request body (index 0) and media type (index 1)
|
||||
public String[] getBody() {
|
||||
String[] requestBody = new String[2];
|
||||
requestBody[0] = rawInputArea.getText();
|
||||
requestBody[1] = rawInputTypeBox.getValue();
|
||||
|
||||
return requestBody;
|
||||
}
|
||||
}
|
|
@ -18,12 +18,13 @@ package com.rohitawate.restaurant.dashboard;
|
|||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXSnackbar;
|
||||
import com.rohitawate.restaurant.models.requests.GETRequest;
|
||||
import com.rohitawate.restaurant.models.requests.POSTRequest;
|
||||
import com.rohitawate.restaurant.models.responses.RestaurantResponse;
|
||||
import com.rohitawate.restaurant.requestsmanager.GETRequestManager;
|
||||
import com.rohitawate.restaurant.requestsmanager.POSTRequestManager;
|
||||
import com.rohitawate.restaurant.requestsmanager.RequestManager;
|
||||
import com.rohitawate.restaurant.settings.Settings;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
|
@ -33,7 +34,9 @@ import javafx.scene.layout.BorderPane;
|
|||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
@ -56,34 +59,40 @@ public class DashboardController implements Initializable {
|
|||
@FXML
|
||||
private JFXButton cancelButton;
|
||||
@FXML
|
||||
private TabPane requestOptionsTab;
|
||||
@FXML
|
||||
private Tab authTab, headersTab, bodyTab;
|
||||
|
||||
private JFXSnackbar snackBar;
|
||||
private final String[] httpMethods = {"GET", "POST", "PUT", "DELETE", "PATCH"};
|
||||
private RequestManager requestManager;
|
||||
private HeaderTabController headerTabController;
|
||||
private BodyTabController bodyTabController;
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
applySettings();
|
||||
Task<Parent> parentLoader = new Task<Parent>() {
|
||||
@Override
|
||||
protected Parent call() throws Exception {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/dashboard/HeaderTab.fxml"));
|
||||
Parent parent = loader.load();
|
||||
headerTabController = loader.getController();
|
||||
return parent;
|
||||
}
|
||||
};
|
||||
|
||||
parentLoader.setOnSucceeded(event -> headersTab.setContent(parentLoader.getValue()));
|
||||
parentLoader.setOnFailed(event -> parentLoader.getException().printStackTrace());
|
||||
new Thread(parentLoader).start();
|
||||
try {
|
||||
// Loading the headers tab
|
||||
FXMLLoader headerTabLoader = new FXMLLoader(getClass().getResource("/fxml/dashboard/HeaderTab.fxml"));
|
||||
Parent headerTabContent = headerTabLoader.load();
|
||||
headerTabController = headerTabLoader.getController();
|
||||
headersTab.setContent(headerTabContent);
|
||||
|
||||
// Loading the body tab
|
||||
FXMLLoader bodyTabLoader = new FXMLLoader(getClass().getResource("/fxml/dashboard/BodyTab.fxml"));
|
||||
Parent bodyTabContent = bodyTabLoader.load();
|
||||
bodyTabController = bodyTabLoader.getController();
|
||||
bodyTab.setContent(bodyTabContent);
|
||||
} catch (IOException IOE) {
|
||||
IOE.printStackTrace();
|
||||
}
|
||||
|
||||
addressField.setText("https://api.chucknorris.io/jokes/random");
|
||||
responseBox.getChildren().remove(0);
|
||||
httpMethodBox.getItems().addAll(httpMethods);
|
||||
httpMethodBox.setValue("GET");
|
||||
httpMethodBox.getSelectionModel().select(1);
|
||||
|
||||
snackBar = new JFXSnackbar(dashboard);
|
||||
bodyTab.disableProperty().bind(Bindings.and(httpMethodBox.valueProperty().isNotEqualTo("POST"),
|
||||
|
@ -133,6 +142,53 @@ public class DashboardController implements Initializable {
|
|||
});
|
||||
requestManager.start();
|
||||
break;
|
||||
case "POST":
|
||||
if (requestManager == null || requestManager.getClass() != POSTRequestManager.class)
|
||||
requestManager = new POSTRequestManager();
|
||||
else if (requestManager.isRunning()) {
|
||||
snackBar.show("Please wait while the current request is processed.", 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] requestBody = bodyTabController.getBody();
|
||||
POSTRequest postRequest = new POSTRequest(addressField.getText());
|
||||
postRequest.setRequestBody(requestBody[0]);
|
||||
|
||||
MediaType requestMediaType = MediaType.WILDCARD_TYPE;
|
||||
switch (requestBody[1]) {
|
||||
case "PLAIN TEXT":
|
||||
requestMediaType = MediaType.TEXT_PLAIN_TYPE;
|
||||
break;
|
||||
case "JSON":
|
||||
requestMediaType = MediaType.APPLICATION_JSON_TYPE;
|
||||
break;
|
||||
case "XML":
|
||||
requestMediaType = MediaType.APPLICATION_XML_TYPE;
|
||||
break;
|
||||
case "HTML":
|
||||
requestMediaType = MediaType.TEXT_HTML_TYPE;
|
||||
break;
|
||||
}
|
||||
postRequest.setRequestBodyMediaType(requestMediaType);
|
||||
postRequest.addHeaders(headerTabController.getHeaders());
|
||||
requestManager.setRequest(postRequest);
|
||||
cancelButton.setOnAction(e -> requestManager.cancel());
|
||||
requestManager.setOnRunning(e -> {
|
||||
responseArea.clear();
|
||||
loadingLayer.setVisible(true);
|
||||
});
|
||||
requestManager.setOnSucceeded(e -> {
|
||||
updateDashboard(requestManager.getValue());
|
||||
loadingLayer.setVisible(false);
|
||||
requestManager.reset();
|
||||
});
|
||||
requestManager.setOnCancelled(e -> {
|
||||
loadingLayer.setVisible(false);
|
||||
snackBar.show("Request canceled.", 2000);
|
||||
requestManager.reset();
|
||||
});
|
||||
requestManager.start();
|
||||
break;
|
||||
default:
|
||||
loadingLayer.setVisible(false);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
|
||||
public class GETRequest extends RestaurantRequest {
|
||||
public GETRequest() {
|
||||
}
|
||||
|
||||
public GETRequest(URL target) {
|
||||
super(target);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2018 Rohit Awate.
|
||||
*
|
||||
* 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.rohitawate.restaurant.models.requests;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class POSTRequest extends RestaurantRequest {
|
||||
private String requestBody;
|
||||
private MediaType requestBodyMediaType;
|
||||
private File binaryBody;
|
||||
|
||||
public POSTRequest() {
|
||||
}
|
||||
|
||||
public POSTRequest(URL target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
public POSTRequest(String target) throws MalformedURLException {
|
||||
super(target);
|
||||
}
|
||||
|
||||
public String getRequestBody() {
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
public void setRequestBody(String requestBody) {
|
||||
this.requestBody = requestBody;
|
||||
}
|
||||
|
||||
public MediaType getRequestBodyMediaType() {
|
||||
return requestBodyMediaType;
|
||||
}
|
||||
|
||||
public void setRequestBodyMediaType(MediaType requestBodyMediaType) {
|
||||
this.requestBodyMediaType = requestBodyMediaType;
|
||||
}
|
||||
}
|
|
@ -24,6 +24,9 @@ public abstract class RestaurantRequest {
|
|||
private URL target;
|
||||
private HashMap<String, String> headers;
|
||||
|
||||
RestaurantRequest() {
|
||||
}
|
||||
|
||||
RestaurantRequest(String target) throws MalformedURLException {
|
||||
this.target = new URL(target);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright 2018 Rohit Awate.
|
||||
*
|
||||
* 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.rohitawate.restaurant.requestsmanager;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.rohitawate.restaurant.models.requests.POSTRequest;
|
||||
import com.rohitawate.restaurant.models.responses.RestaurantResponse;
|
||||
import javafx.concurrent.Task;
|
||||
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.client.Invocation;
|
||||
import javax.ws.rs.client.WebTarget;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class POSTRequestManager extends RequestManager {
|
||||
@Override
|
||||
protected Task<RestaurantResponse> createTask() {
|
||||
return new Task<RestaurantResponse>() {
|
||||
@Override
|
||||
protected RestaurantResponse call() throws Exception {
|
||||
RestaurantResponse response = new RestaurantResponse();
|
||||
WebTarget target = client.target(request.getTarget().toString());
|
||||
|
||||
Invocation.Builder requestBuilder = target.request();
|
||||
|
||||
HashMap<String, String> headers = request.getHeaders();
|
||||
Map.Entry<String, String> mapEntry;
|
||||
|
||||
for (Map.Entry entry : headers.entrySet()) {
|
||||
mapEntry = (Map.Entry) entry;
|
||||
requestBuilder.header(mapEntry.getKey(), mapEntry.getValue());
|
||||
}
|
||||
|
||||
long initialTime = System.currentTimeMillis();
|
||||
Response serverResponse = requestBuilder.post(Entity.entity(((POSTRequest) request).getRequestBody(),
|
||||
((POSTRequest) request).getRequestBodyMediaType()));
|
||||
response.setTime(initialTime, System.currentTimeMillis());
|
||||
|
||||
if (serverResponse == null)
|
||||
throw new IOException();
|
||||
else if (serverResponse.getStatus() == 301) {
|
||||
response.setStatusCode(301);
|
||||
String newLocation = serverResponse.getHeaderString("location");
|
||||
String responseHelpText;
|
||||
|
||||
if (newLocation == null)
|
||||
responseHelpText = "The resource has been permanently moved to another location.\n\n" +
|
||||
"Here's what you can do:\n" +
|
||||
"- Find the new URL from the API documentation.\n" +
|
||||
"- Try using https instead of http if you're not already.";
|
||||
else
|
||||
responseHelpText = "The resource has been permanently moved to: " + newLocation;
|
||||
|
||||
response.setBody(responseHelpText);
|
||||
return response;
|
||||
}
|
||||
|
||||
String type = (String) serverResponse.getHeaders().getFirst("Content-type");
|
||||
String responseBody = serverResponse.readEntity(String.class);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
|
||||
switch (type.toLowerCase()) {
|
||||
case "application/json; charset=utf-8":
|
||||
case "application/json":
|
||||
JsonNode node = mapper.readTree(responseBody);
|
||||
response.setBody(mapper.writeValueAsString(node));
|
||||
break;
|
||||
case "application/xml; charset=utf-8":
|
||||
case "application/xml":
|
||||
response.setBody(mapper.writeValueAsString(responseBody));
|
||||
break;
|
||||
case "text/html":
|
||||
case "text/html; charset=utf-8":
|
||||
response.setBody(responseBody);
|
||||
break;
|
||||
default:
|
||||
response.setBody(responseBody);
|
||||
}
|
||||
|
||||
response.setMediaType(serverResponse.getMediaType());
|
||||
response.setStatusCode(serverResponse.getStatus());
|
||||
response.setSize(responseBody.length());
|
||||
|
||||
return response;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -7,11 +7,11 @@
|
|||
-fx-text-fill: white;
|
||||
}
|
||||
|
||||
#httpMethodBox {
|
||||
.combo-box {
|
||||
-fx-background-color: #707070;
|
||||
}
|
||||
|
||||
#httpMethodBox .list-cell {
|
||||
.combo-box .list-cell {
|
||||
-fx-background-color: #707070;
|
||||
-fx-pref-height: 39px;
|
||||
-fx-font-size: 18px;
|
||||
|
@ -19,16 +19,16 @@
|
|||
-fx-padding: 0 0 0 10px;
|
||||
}
|
||||
|
||||
#httpMethodBox .list-cell:hover {
|
||||
.combo-box .list-cell:hover {
|
||||
-fx-background-color: orangered;
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
|
||||
#httpMethodBox .arrow-button .arrow {
|
||||
.combo-box .arrow-button .arrow {
|
||||
-fx-background-color: white;
|
||||
}
|
||||
|
||||
#httpMethodBox .list-view {
|
||||
.combo-box .list-view {
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
|
@ -40,23 +40,20 @@
|
|||
-fx-background-color: #1b1b1b;
|
||||
}
|
||||
|
||||
#responseArea {
|
||||
.text-area {
|
||||
-fx-font-family: "Liberation Mono";
|
||||
-fx-text-fill: #a1a1a1;
|
||||
-fx-background-radius: 0;
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: transparent;
|
||||
-fx-border-width: 0px;
|
||||
}
|
||||
|
||||
#responseArea .content {
|
||||
.text-area .content {
|
||||
-fx-background-radius: 0;
|
||||
-fx-background-color: #2a2a2a;
|
||||
}
|
||||
|
||||
#responseArea {
|
||||
-fx-border-width: 0px;
|
||||
}
|
||||
|
||||
#loadingLayer {
|
||||
-fx-background-color: #bf8829;
|
||||
}
|
||||
|
@ -70,7 +67,7 @@
|
|||
}
|
||||
|
||||
.tab-pane:top .tab-header-area .tab-header-background {
|
||||
-fx-background-color: #2f2f2f;
|
||||
-fx-background-color: #6a6a6a;
|
||||
}
|
||||
|
||||
.tab-pane .tab-content-area,
|
||||
|
@ -83,6 +80,14 @@
|
|||
-fx-background-color: #3d3d3d;
|
||||
}
|
||||
|
||||
/* Tab attributes */
|
||||
.tab {
|
||||
-fx-background-radius: 0;
|
||||
-fx-background-insets: 0;
|
||||
-fx-focus-color: transparent;
|
||||
-fx-faint-focus-color: transparent;
|
||||
}
|
||||
|
||||
.tab-pane:top .tab-header-area .headers-region .tab:top {
|
||||
-fx-background-color: #6a6a6a;
|
||||
}
|
||||
|
@ -91,6 +96,7 @@
|
|||
-fx-background-color: #55a15c;
|
||||
}
|
||||
|
||||
/* Tab titles */
|
||||
.tab-pane:top .tab-header-area .headers-region .tab:top .tab-container .tab-label .text {
|
||||
-fx-fill: #b8b8b8;
|
||||
}
|
||||
|
@ -99,11 +105,14 @@
|
|||
-fx-fill: white;
|
||||
}
|
||||
|
||||
.tab {
|
||||
-fx-background-radius: 0;
|
||||
-fx-background-insets: 0;
|
||||
-fx-focus-color: transparent;
|
||||
-fx-faint-focus-color: transparent;
|
||||
/* Tabs in the request 'Body' option */
|
||||
#bodyTabPane:top .tab-header-area .tab-header-background,
|
||||
#bodyTabPane:top .tab-header-area .headers-region .tab:top {
|
||||
-fx-background-color: #3d3d3d;
|
||||
}
|
||||
|
||||
#bodyTabPane .tab-header-area .headers-region .tab:selected:top {
|
||||
-fx-background-color: #4e848f;
|
||||
}
|
||||
|
||||
.scroll-pane .scroll-bar:vertical .thumb {
|
||||
|
|
58
src/main/resources/fxml/dashboard/BodyTab.fxml
Normal file
58
src/main/resources/fxml/dashboard/BodyTab.fxml
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright 2018 Rohit Awate.
|
||||
~
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<TabPane fx:id="bodyTabPane" stylesheets="@../../css/Default.css" tabClosingPolicy="UNAVAILABLE" tabMinWidth="100.0"
|
||||
xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111"
|
||||
fx:controller="com.rohitawate.restaurant.dashboard.BodyTabController">
|
||||
<tabs>
|
||||
<Tab text="RAW">
|
||||
<content>
|
||||
<ScrollPane fitToHeight="true" fitToWidth="true" hbarPolicy="NEVER" vbarPolicy="ALWAYS">
|
||||
<content>
|
||||
<VBox alignment="CENTER">
|
||||
<children>
|
||||
<HBox alignment="CENTER_LEFT" VBox.vgrow="ALWAYS">
|
||||
<children>
|
||||
<ComboBox fx:id="rawInputTypeBox" HBox.hgrow="ALWAYS">
|
||||
<HBox.margin>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||
</HBox.margin>
|
||||
</ComboBox>
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets/>
|
||||
</VBox.margin>
|
||||
</HBox>
|
||||
<TextArea fx:id="rawInputArea" promptText="Raw data goes here..." wrapText="true"
|
||||
VBox.vgrow="ALWAYS">
|
||||
<VBox.margin>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0"/>
|
||||
</VBox.margin>
|
||||
</TextArea>
|
||||
</children>
|
||||
</VBox>
|
||||
</content>
|
||||
</ScrollPane>
|
||||
</content>
|
||||
</Tab>
|
||||
<Tab text="BINARY"/>
|
||||
</tabs>
|
||||
</TabPane>
|
|
@ -70,7 +70,7 @@
|
|||
<items>
|
||||
<AnchorPane maxHeight="250.0">
|
||||
<children>
|
||||
<TabPane fx:id="requestTabs" maxHeight="200.0" minHeight="200.0"
|
||||
<TabPane fx:id="requestOptionsTab" maxHeight="200.0" minHeight="200.0"
|
||||
tabClosingPolicy="UNAVAILABLE" tabMinWidth="150.0" AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0">
|
||||
|
|
Loading…
Reference in a new issue