diff --git a/README.md b/README.md
index 4cf1226..ce0a1de 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Spaceship :rocket:
-![v1.4.0](https://github.com/sebastian4j/spaceship/blob/main/images/v1.4.0.png?raw=true)
+![v1.5.0](https://github.com/sebastian4j/spaceship/blob/main/images/v1.5.0.png?raw=true)
- Es una aplicación escrita en Java 17, JavaFX y compilable con GraalVM para una ejecución nativa.
- Permite hacer peticiones a urls y visualizar la respuesta.
@@ -17,6 +17,7 @@
- guardar el response obtenido
- ver los milisegundos y bytes transferidos
- muestra el código de estado http obtenido
+ - guardar el response directo a un archivo sin mostrar el contenido
- Compilar la app:
```
@@ -25,10 +26,10 @@ mvn clean package
- Lanzar la app:
```
linux:
-java --module-path target/spaceship-1.4.0.jar:target/lib/ --module com.github.sebastian4j.spaceship/com.github.sebastian4j.spaceship.Spaceship
+java --module-path target/spaceship-1.5.0.jar:target/lib/ --module com.github.sebastian4j.spaceship/com.github.sebastian4j.spaceship.Spaceship
windows:
-java --module-path target/spaceship-1.4.0.jar;target/lib/ --module com.github.sebastian4j.spaceship/com.github.sebastian4j.spaceship.Spaceship
+java --module-path target/spaceship-1.5.0.jar;target/lib/ --module com.github.sebastian4j.spaceship/com.github.sebastian4j.spaceship.Spaceship
```
- Para compilarlo en forma nativa:
- descargar graalvm-ce-java17-22.1.0 (me imagino que funciona con versiones posteriores)
diff --git a/images/v1.5.0.png b/images/v1.5.0.png
new file mode 100644
index 0000000..8893d5e
Binary files /dev/null and b/images/v1.5.0.png differ
diff --git a/pom.xml b/pom.xml
index 504afcd..6238fb9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.github.sebastian4j
spaceship
- 1.4.0
+ 1.5.0
UTF-8
17
@@ -111,6 +111,7 @@
javafx.scene.control.MenuItem
impl.jfxtras.styles.jmetro.FluentButtonSkin
impl.jfxtras.styles.jmetro.TextFieldSkin
+ javafx.scene.control.Alert
com.github.sebastian4j.spaceship.fxml.RequestController
com.github.sebastian4j.spaceship.fxml.RequestTabController
com.github.sebastian4j.spaceship.dto.GUIRequest
diff --git a/src/main/java/com/github/sebastian4j/spaceship/dto/RequestResponse.java b/src/main/java/com/github/sebastian4j/spaceship/dto/RequestResponse.java
index 42c4d8b..8c8dc4d 100644
--- a/src/main/java/com/github/sebastian4j/spaceship/dto/RequestResponse.java
+++ b/src/main/java/com/github/sebastian4j/spaceship/dto/RequestResponse.java
@@ -3,5 +3,5 @@
import java.util.List;
import java.util.Map;
-public record RequestResponse(String body, Map> headers, long bytes, String statusCode) {
+public record RequestResponse(String body, Map> headers, long bytes, String statusCode, byte[] response) {
}
diff --git a/src/main/java/com/github/sebastian4j/spaceship/fxml/RequestTabController.java b/src/main/java/com/github/sebastian4j/spaceship/fxml/RequestTabController.java
index 6b11e7f..f614680 100644
--- a/src/main/java/com/github/sebastian4j/spaceship/fxml/RequestTabController.java
+++ b/src/main/java/com/github/sebastian4j/spaceship/fxml/RequestTabController.java
@@ -30,62 +30,48 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
public class RequestTabController implements Initializable, FileLoader {
private static final System.Logger LOGGER = System.getLogger(RequestTabController.class.getName());
@FXML
private FlowPane a;
-
@FXML
private Button addHeader;
-
@FXML
private TextArea bodyresult;
-
@FXML
private VBox containerHeader;
-
@FXML
private VBox containerHeaderResponse;
-
@FXML
private ComboBox methods;
-
@FXML
private TextArea requestbody;
-
@FXML
private ScrollPane scrollHeaders;
-
@FXML
private Button send;
-
@FXML
private Tab tab1;
-
@FXML
private Tab tab2;
-
@FXML
private Text textFlowPaneResponse;
-
@FXML
private TextField url;
-
@FXML
private VBox vboxurl;
-
@FXML
private HBox hboxResponse;
-
@FXML
private VBox vboxResultResponse;
-
@FXML
private BorderPane contenedor;
-
@FXML
private TabPane tabsContainer;
+ @FXML
+ private CheckBox onlySave;
private ResourceBundle rb;
private File last;
@@ -94,6 +80,7 @@ public class RequestTabController implements Initializable, FileLoader {
private Task runningTask;
private Future> future;
private RequestResponseUtils requestResponseUtils = new RequestResponseUtils();
+ private File saveResponse = null;
@FXML
void addHeader(ActionEvent event) {
addHeader(null, null);
@@ -147,48 +134,70 @@ private void calculateHeaderResponseWidth(TextField tfk, TextField tfv) {
tfv.setPrefWidth(widthVal);
}
+ private File fileToSaveRequest() {
+ FileChooser fileChooser = new FileChooser();
+ fileChooser.setTitle(rb.getString("file.chooser.save"));
+ fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter(rb.getString("file.chooser.all.files"), "*.*"));
+ return fileChooser.showSaveDialog(null);
+ }
+
private void sendRequest() {
+ saveResponse = null;
+ var toFile = onlySave.isSelected();
+ var send = new AtomicBoolean(true);
+ if (toFile) {
+ saveResponse = fileToSaveRequest();
+ if (saveResponse == null) {
+ send.set(false);
+ FXMLUtils.showWarningAlert(rb.getString("only.save.error.title"), rb.getString("only.save.error.text"));
+ }
+ }
+
runningTask = new Task<>() {
@Override
protected Void call() {
try {
- LOGGER.log(System.Logger.Level.INFO, "enviando request");
- var ini = System.currentTimeMillis();
- var result = requestResponseUtils.sendRequest(
- url.getText(), FXMLUtils.headers(containerHeader),
- HttpMethods.hasBody(methods.getSelectionModel().getSelectedItem()), requestbody.getText());
- var res = System.currentTimeMillis() - ini;
- Platform.runLater(() -> {
- textFlowPaneResponse.setText(
- rb.getString("milis") + ": " + res +
- " bytes: " + result.bytes() +
- " status: " + result.statusCode());
- VBox vb = new VBox();
- containerHeaderResponse.getChildren().clear();
- result.headers().forEach((a, b) -> {
- for (var val : b) {
- var key = new TextField(a);
- key.setMinWidth(300);
- var value = new TextField(val);
- value.setMinWidth(400);
- var hbox = new HBox(key, value);
- hbox.setSpacing(2);
- hbox.setAlignment(Pos.CENTER);
- vb.getChildren().add(hbox);
- calculateHeaderResponseWidth(key, value);
- stage.widthProperty().addListener((observableValue, number, t1) ->
- calculateHeaderResponseWidth(key, value)
- );
- }
+ if (send.get()) {
+ LOGGER.log(System.Logger.Level.INFO, "enviando request");
+ var ini = System.currentTimeMillis();
+ var result = requestResponseUtils.sendRequest(
+ url.getText(), FXMLUtils.headers(containerHeader),
+ HttpMethods.hasBody(methods.getSelectionModel().getSelectedItem()), requestbody.getText(),
+ saveResponse);
+
+ var res = System.currentTimeMillis() - ini;
+ Platform.runLater(() -> {
+ textFlowPaneResponse.setText(
+ rb.getString("milis") + ": " + res +
+ " bytes: " + result.bytes() +
+ " status: " + result.statusCode());
+ VBox vb = new VBox();
+ containerHeaderResponse.getChildren().clear();
+ result.headers().forEach((a, b) -> {
+ for (var val : b) {
+ var key = new TextField(a);
+ key.setMinWidth(300);
+ var value = new TextField(val);
+ value.setMinWidth(400);
+ var hbox = new HBox(key, value);
+ hbox.setSpacing(2);
+ hbox.setAlignment(Pos.CENTER);
+ vb.getChildren().add(hbox);
+ calculateHeaderResponseWidth(key, value);
+ stage.widthProperty().addListener((observableValue, number, t1) ->
+ calculateHeaderResponseWidth(key, value)
+ );
+ }
+ });
+ var sp = new HBox();
+ sp.setMinHeight(50); // espacio al final
+ vb.getChildren().add(sp);
+ containerHeaderResponse.getChildren().add(vb);
+ bodyresult.setText(result.body());
+ tabsContainer.getSelectionModel().select(tab2);
});
- var sp = new HBox();
- sp.setMinHeight(50); // espacio al final
- vb.getChildren().add(sp);
- containerHeaderResponse.getChildren().add(vb);
- bodyresult.setText(result.body());
- tabsContainer.getSelectionModel().select(tab2);
- });
- LOGGER.log(System.Logger.Level.INFO, "request finalizado");
+ LOGGER.log(System.Logger.Level.INFO, "request finalizado");
+ }
} catch (Exception e) {
LOGGER.log(System.Logger.Level.ERROR, "error al enviar request", e);
}
@@ -254,10 +263,11 @@ public void initialize(URL url, ResourceBundle rb) {
scrollHeaders.widthProperty().addListener(cl -> {
containerHeader.setMinWidth(scrollHeaders.getWidth());
containerHeaderResponse.setMinWidth(scrollHeaders.getWidth());
- this.url.setMinWidth(scrollHeaders.getWidth() - send.getWidth() - methods.getWidth() - 50);
+ this.url.setMinWidth(scrollHeaders.getWidth() - send.getWidth() - methods.getWidth() - 100);
});
vboxResultResponse.heightProperty().addListener((observableValue, number, t1) -> resize());
resize();
+ onlySave.setTooltip(new Tooltip(rb.getString("only.save")));
}
private void resize() {
diff --git a/src/main/java/com/github/sebastian4j/spaceship/utils/FXMLUtils.java b/src/main/java/com/github/sebastian4j/spaceship/utils/FXMLUtils.java
index c7e1a42..f05a0ee 100644
--- a/src/main/java/com/github/sebastian4j/spaceship/utils/FXMLUtils.java
+++ b/src/main/java/com/github/sebastian4j/spaceship/utils/FXMLUtils.java
@@ -3,6 +3,7 @@
import com.github.sebastian4j.spaceship.dto.GUIRequest;
import com.github.sebastian4j.spaceship.dto.Header;
import javafx.scene.Node;
+import javafx.scene.control.Alert;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
@@ -68,4 +69,11 @@ public static Map headers(VBox container) {
});
return headers;
}
+
+ public static void showWarningAlert(String title, String text) {
+ var alert = new Alert(Alert.AlertType.WARNING);
+ alert.setTitle(title);
+ alert.setContentText(text);
+ alert.show();
+ }
}
diff --git a/src/main/java/com/github/sebastian4j/spaceship/utils/RequestResponseUtils.java b/src/main/java/com/github/sebastian4j/spaceship/utils/RequestResponseUtils.java
index 7c0d1ec..49b4a06 100644
--- a/src/main/java/com/github/sebastian4j/spaceship/utils/RequestResponseUtils.java
+++ b/src/main/java/com/github/sebastian4j/spaceship/utils/RequestResponseUtils.java
@@ -2,6 +2,8 @@
import com.github.sebastian4j.spaceship.dto.RequestResponse;
+import java.io.File;
+import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
@@ -33,7 +35,8 @@ public void kill() {
}
}
- public RequestResponse sendRequest(final String url, Map headers, boolean withBody, final String body) {
+ public RequestResponse sendRequest(final String url, Map headers, boolean withBody,
+ final String body, File toFile) {
String result = "";
final var sb = new StringBuilder();
final var bytes = new AtomicLong();
@@ -56,11 +59,20 @@ public RequestResponse sendRequest(final String url, Map headers
String res = "";
int lee;
LOGGER.log(System.Logger.Level.INFO, "leyendo en thread");
- while ((lee = is.read()) != -1) {
- sb.append((char) lee);
+ if (toFile == null) { // retornar la salida
+ while ((lee = is.read()) != -1) {
+ sb.append((char) lee);
+ }
+ res = sb.toString();
+ bytes.set(res.getBytes(StandardCharsets.UTF_8).length);
+ } else { // guardar en archivo la salida
+ try (var os = new FileOutputStream(toFile)) {
+ var br = is.readAllBytes();
+ os.write(br);
+ bytes.set(br.length);
+ }
}
- res = sb.toString();
- bytes.set(res.getBytes(StandardCharsets.UTF_8).length);
+
}
hr.putAll(con.getHeaderFields());
} catch (Exception e) {
@@ -79,7 +91,7 @@ public RequestResponse sendRequest(final String url, Map headers
LOGGER.log(System.Logger.Level.ERROR, "error al enviar request", e);
result = e.getMessage() + " ~ " + readError();
}
- return new RequestResponse(result, hr, bytes.get(), statusCode[0]);
+ return new RequestResponse(result, hr, bytes.get(), statusCode[0], new byte[]{});
}
private String readError() {
diff --git a/src/main/resources/label.properties b/src/main/resources/label.properties
index 5a25fd5..fe9a477 100644
--- a/src/main/resources/label.properties
+++ b/src/main/resources/label.properties
@@ -21,4 +21,8 @@ milis=miliseconds
cancel.send=Cancel
no.name=Default
file.extension=spc
-file.quick.save=Save
\ No newline at end of file
+file.quick.save=Save
+only.save=response to file
+only.save.error.title=Unable to save response
+only.save.error.text=Select the destination file
+only.save.response=save
\ No newline at end of file
diff --git a/src/main/resources/requestTab.fxml b/src/main/resources/requestTab.fxml
index 7f615d4..f42f9f2 100644
--- a/src/main/resources/requestTab.fxml
+++ b/src/main/resources/requestTab.fxml
@@ -3,6 +3,7 @@
+
@@ -14,8 +15,13 @@
-
+
+
+
+
+
+