Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add websocket support #210

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions lib/consts.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import 'dart:io';
import 'dart:convert';
import 'dart:io';

import 'package:davi/davi.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:davi/davi.dart';

const kDiscordUrl = "https://bit.ly/heyfoss";
const kGitUrl = "https://github.com/foss42/apidash";
Expand Down Expand Up @@ -235,6 +236,9 @@ final kColorStatusCode400 = Colors.red.shade800;
final kColorStatusCode500 = Colors.amber.shade900;
const kOpacityDarkModeBlend = 0.4;

final kColorProtocolHttp = Colors.blue.shade800;
final kColorProtocolWebSocket = Colors.red.shade800;

final kColorHttpMethodGet = Colors.green.shade800;
final kColorHttpMethodHead = kColorHttpMethodGet;
final kColorHttpMethodPost = Colors.blue.shade800;
Expand All @@ -246,17 +250,22 @@ enum RequestItemMenuOption { edit, delete, duplicate }

enum HTTPVerb { get, head, post, put, patch, delete }

enum Protocol { http, websocket }

enum FormDataType { text, file }

const kSupportedUriSchemes = ["https", "http"];
const kDefaultUriScheme = "https";
const kSupportedHTTPUriSchemes = ["https", "http"];
const kSupportedWebSocketUriSchemes = ["ws", "wss"];
const kDefaultHTTPUriScheme = "https";
const kDefaultWebSocketUriScheme = "wss";
const kMethodsWithBody = [
HTTPVerb.post,
HTTPVerb.put,
HTTPVerb.patch,
HTTPVerb.delete,
];

const kDefaultProtocol = Protocol.http;
const kDefaultHttpMethod = HTTPVerb.get;
const kDefaultContentType = ContentType.json;

Expand Down Expand Up @@ -495,15 +504,21 @@ const kAudioError =

const kRaiseIssue =
"\nPlease raise an issue in API Dash GitHub repo so that we can resolve it.";

const kCsvError =
"There seems to be an issue rendering this CSV. Please raise an issue in API Dash GitHub repo so that we can resolve it.";

const kHintTextUrlCard = "Enter API endpoint like api.foss42.com/country/codes";
const kHintTextHTTPUrlCard =
"Enter API endpoint like api.foss42.com/country/codes";
const kHintTextWebSocketUrlCard =
"Enter WebSocket server like wss://echo.websocket.org";

const kLabelPlusNew = "+ New";
const kLabelSend = "Send";
const kLabelSending = "Sending..";
const kLabelConnect = "Connect";
const kLabelDisconnect = "Disconnect";
const kLabelBusy = "Busy";
const kLabelCopy = "Copy";
const kLabelDelete = "Delete";
const kLabelSave = "Save";
const kLabelDownload = "Download";
45 changes: 44 additions & 1 deletion lib/models/request_model.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import 'dart:io';

import 'package:apidash/services/websocket_service.dart';
import 'package:flutter/foundation.dart';

import '../consts.dart';
import '../utils/utils.dart'
show
mapListToFormDataModelRows,
rowsToFormDataMapList,
mapToRows,
rowsToMap,
getEnabledRows;
import '../consts.dart';
import 'models.dart';

@immutable
class RequestModel {
const RequestModel({
required this.id,
this.protocol = Protocol.http,
this.method = HTTPVerb.get,
this.url = "",
this.name = "",
Expand All @@ -29,9 +33,12 @@ class RequestModel {
this.responseStatus,
this.message,
this.responseModel,
this.webSocketMessages,
this.webSocketManager,
});

final String id;
final Protocol protocol;
final HTTPVerb method;
final String url;
final String name;
Expand All @@ -47,6 +54,7 @@ class RequestModel {
final int? responseStatus;
final String? message;
final ResponseModel? responseModel;
final List<WebSocketMessage>? webSocketMessages;

List<NameValueModel>? get enabledRequestHeaders =>
getEnabledRows(requestHeaders, isHeaderEnabledList);
Expand All @@ -67,11 +75,14 @@ class RequestModel {
bool get hasContentTypeHeader => enabledHeadersMap.keys
.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader);

final WebSocketManager? webSocketManager;

RequestModel duplicate({
required String id,
}) {
return RequestModel(
id: id,
protocol: protocol,
method: method,
url: url,
name: "$name (copy)",
Expand All @@ -86,11 +97,13 @@ class RequestModel {
requestBody: requestBody,
requestFormDataList:
requestFormDataList != null ? [...requestFormDataList!] : null,
webSocketMessages: webSocketMessages,
);
}

RequestModel copyWith({
String? id,
Protocol? protocol,
HTTPVerb? method,
String? url,
String? name,
Expand All @@ -106,13 +119,16 @@ class RequestModel {
int? responseStatus,
String? message,
ResponseModel? responseModel,
List<WebSocketMessage>? webSocketMessages,
WebSocketManager? webSocketManager,
}) {
var headers = requestHeaders ?? this.requestHeaders;
var params = requestParams ?? this.requestParams;
var enabledHeaders = isHeaderEnabledList ?? this.isHeaderEnabledList;
var enabledParams = isParamEnabledList ?? this.isParamEnabledList;
return RequestModel(
id: id ?? this.id,
protocol: protocol ?? this.protocol,
method: method ?? this.method,
url: url ?? this.url,
name: name ?? this.name,
Expand All @@ -129,12 +145,16 @@ class RequestModel {
responseStatus: responseStatus ?? this.responseStatus,
message: message ?? this.message,
responseModel: responseModel ?? this.responseModel,
webSocketMessages: webSocketMessages ?? this.webSocketMessages,
webSocketManager: webSocketManager ?? this.webSocketManager,
);
}

factory RequestModel.fromJson(Map<String, dynamic> data) {
Protocol protocol;
HTTPVerb method;
ContentType requestBodyContentType;
List<WebSocketMessage>? webSocketMessages;
ResponseModel? responseModel;

final id = data["id"] as String;
Expand All @@ -143,6 +163,11 @@ class RequestModel {
} catch (e) {
method = kDefaultHttpMethod;
}
try {
protocol = Protocol.values.byName(data["protocol"] as String);
} catch (e) {
protocol = kDefaultProtocol;
}
final url = data["url"] as String;
final name = data["name"] as String?;
final description = data["description"] as String?;
Expand All @@ -160,6 +185,12 @@ class RequestModel {
final requestFormDataList = data["requestFormDataList"];
final responseStatus = data["responseStatus"] as int?;
final message = data["message"] as String?;

if (data["webSocketMessages"] != null) {
webSocketMessages = (data["webSocketMessages"] as List)
.map((e) => WebSocketMessage.fromJson(Map<String, dynamic>.from(e)))
.toList();
}
final responseModelJson = data["responseModel"];

if (responseModelJson != null) {
Expand All @@ -171,6 +202,7 @@ class RequestModel {

return RequestModel(
id: id,
protocol: protocol,
method: method,
url: url,
name: name ?? "",
Expand All @@ -191,13 +223,15 @@ class RequestModel {
: null,
responseStatus: responseStatus,
message: message,
webSocketMessages: webSocketMessages,
responseModel: responseModel,
);
}

Map<String, dynamic> toJson({bool includeResponse = true}) {
return {
"id": id,
"protocol": protocol.name,
"method": method.name,
"url": url,
"name": name,
Expand All @@ -211,6 +245,9 @@ class RequestModel {
"requestFormDataList": rowsToFormDataMapList(requestFormDataList),
"responseStatus": includeResponse ? responseStatus : null,
"message": includeResponse ? message : null,
"webSocketMessages": includeResponse
? webSocketMessages?.map((e) => e.toJson()).toList()
: null,
"responseModel": includeResponse ? responseModel?.toJson() : null,
};
}
Expand All @@ -219,6 +256,7 @@ class RequestModel {
String toString() {
return [
"Request Id: $id",
"Request Protocol: ${protocol.name}",
"Request Method: ${method.name}",
"Request URL: $url",
"Request Name: $name",
Expand All @@ -233,6 +271,7 @@ class RequestModel {
"Request FormData: ${requestFormDataList.toString()}",
"Response Status: $responseStatus",
"Response Message: $message",
"WebSocket Messages: ${webSocketMessages.toString()}",
"Response: ${responseModel.toString()}"
].join("\n");
}
Expand All @@ -242,6 +281,7 @@ class RequestModel {
return other is RequestModel &&
other.runtimeType == runtimeType &&
other.id == id &&
other.protocol == protocol &&
other.method == method &&
other.url == url &&
other.name == name &&
Expand All @@ -256,6 +296,7 @@ class RequestModel {
other.requestFormDataList == requestFormDataList &&
other.responseStatus == responseStatus &&
other.message == message &&
other.webSocketMessages == webSocketMessages &&
other.responseModel == responseModel;
}

Expand All @@ -264,6 +305,7 @@ class RequestModel {
return Object.hash(
runtimeType,
id,
protocol,
method,
url,
name,
Expand All @@ -278,6 +320,7 @@ class RequestModel {
requestFormDataList,
responseStatus,
message,
webSocketMessages,
responseModel,
);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/models/settings_model.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:apidash/consts.dart';
import 'package:flutter/material.dart';

@immutable
class SettingsModel {
Expand All @@ -8,7 +8,7 @@ class SettingsModel {
this.alwaysShowCollectionPaneScrollbar = true,
this.size,
this.offset,
this.defaultUriScheme = kDefaultUriScheme,
this.defaultUriScheme = kDefaultHTTPUriScheme,
this.defaultCodeGenLang = CodegenLanguage.curl,
this.saveResponses = true,
this.promptBeforeClosing = true,
Expand Down
Loading