├── styles ├── empty.css ├── dark-theme.css └── home.css ├── db.json ├── images ├── bg.png ├── logo.png ├── logo-dark.png ├── logo-light.png ├── logo-purple.png └── screenshot │ ├── mac_ss_1.png │ ├── mac_ss_2.png │ ├── mac_ss_3.png │ ├── mac_ss_4.png │ └── mac_ss_5.png ├── renderers ├── response.js ├── home.js ├── history.js ├── collection.js ├── settings.js ├── send.js └── request.js ├── package.json ├── README.md ├── main.js ├── .gitignore └── pages └── home.html /styles/empty.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /db.json: -------------------------------------------------------------------------------- 1 | { 2 | "history": [], 3 | "collection": [] 4 | } -------------------------------------------------------------------------------- /images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/bg.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/logo.png -------------------------------------------------------------------------------- /images/logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/logo-dark.png -------------------------------------------------------------------------------- /images/logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/logo-light.png -------------------------------------------------------------------------------- /images/logo-purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/logo-purple.png -------------------------------------------------------------------------------- /images/screenshot/mac_ss_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/screenshot/mac_ss_1.png -------------------------------------------------------------------------------- /images/screenshot/mac_ss_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/screenshot/mac_ss_2.png -------------------------------------------------------------------------------- /images/screenshot/mac_ss_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/screenshot/mac_ss_3.png -------------------------------------------------------------------------------- /images/screenshot/mac_ss_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/screenshot/mac_ss_4.png -------------------------------------------------------------------------------- /images/screenshot/mac_ss_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orcuntuna/guvercin/HEAD/images/screenshot/mac_ss_5.png -------------------------------------------------------------------------------- /renderers/response.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | response_editor = ace.edit("response-editor", { 4 | minLines: 18, 5 | maxLines: 9999 6 | }); 7 | 8 | var JSONMode = require("ace-builds/src/mode-json").Mode; 9 | response_editor.session.setMode(new JSONMode()); 10 | response_editor.setTheme(require('ace-builds/src/theme-xcode')); 11 | response_editor.setFontSize("14px"); 12 | response_editor.setReadOnly(true); 13 | 14 | }); -------------------------------------------------------------------------------- /renderers/home.js: -------------------------------------------------------------------------------- 1 | const remote = require("electron").remote; 2 | const Swal = require('sweetalert2'); 3 | const ace = require('ace-builds/src/ace'); 4 | var xml_beautify = require('xml-formatter'); 5 | const low = require('lowdb'); 6 | const FileSync = require('lowdb/adapters/FileSync'); 7 | const { ipcRenderer, ipcMain } = require('electron'); 8 | const path = require("path"); 9 | 10 | const app = remote.app; 11 | const db_path = path.join(app.getPath('home'), "/.guvercin.json"); 12 | 13 | const adapter = new FileSync(db_path); 14 | const db = low(adapter); 15 | 16 | db.defaults({ history: [], collection: [] }).write(); 17 | const fetch = require("node-fetch"); 18 | 19 | var body_editor; 20 | var response_editor; 21 | -------------------------------------------------------------------------------- /styles/dark-theme.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #333; 3 | color: #fff; 4 | } 5 | 6 | #drawer { 7 | background-color: #222; 8 | color: #fff; 9 | } 10 | 11 | #drawer select { 12 | background-color: #333; 13 | color: #fff; 14 | border-color: transparent; 15 | } 16 | 17 | #send { 18 | background-color: #e36209; 19 | } 20 | 21 | #save { 22 | background-color: #666; 23 | } 24 | 25 | section { 26 | background-color: #333; 27 | } 28 | 29 | input.form-control { 30 | background-color: #ecf0f1; 31 | } 32 | 33 | a, 34 | span.logo { 35 | color: #fff !important; 36 | } 37 | 38 | section.request-bar, 39 | .container-fluid .nav, 40 | .nav .nav-tabs { 41 | background-color: #222; 42 | } 43 | 44 | .props, 45 | .response { 46 | background-color: #333; 47 | } 48 | 49 | .custom-tabs .nav-link.active { 50 | background-color: #161616; 51 | border-color: #e36209 #333 transparent; 52 | border-bottom-color: transparent; 53 | } 54 | 55 | .nav-tabs { 56 | border-bottom: 1px solid #000; 57 | } 58 | .nav-tabs .nav-link.active:hover { 59 | border-top-color: #e36209; 60 | } 61 | 62 | .nav-tabs .nav-link:hover { 63 | border-color: transparent; 64 | } 65 | 66 | #method-select { 67 | background-color: #666; 68 | color: #fff; 69 | border-color: transparent; 70 | } 71 | 72 | .xdsoft_autocomplete_dropdown{ 73 | color: #333; 74 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "guvercin", 3 | "version": "1.0.1", 4 | "description": "rest api client app", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "electron .", 8 | "dist": "build --linux snap" 9 | }, 10 | "repository": "https://github.com/orcuntuna/guvercin", 11 | "author": "Arkkod ", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "electron": "^7.1.7", 15 | "electron-builder": "^21.2.0", 16 | "electron-global": "0.0.2" 17 | }, 18 | "dependencies": { 19 | "ace-builds": "^1.4.7", 20 | "bootstrap": "^4.4.1", 21 | "font-awesome": "^4.7.0", 22 | "jquery": "^3.4.1", 23 | "jquery-autocomplete": "^1.2.8", 24 | "lowdb": "^1.0.0", 25 | "node-fetch": "^2.6.0", 26 | "sweetalert2": "^9.5.4", 27 | "validate.js": "^0.13.1", 28 | "xml-formatter": "^1.2.0" 29 | }, 30 | "keywords": [ 31 | "guvercin", 32 | "rest", 33 | "api", 34 | "client", 35 | "json", 36 | "xml", 37 | "post", 38 | "get", 39 | "request", 40 | "response", 41 | "postman", 42 | "güvercin", 43 | "response" 44 | ], 45 | "build": { 46 | "appId": "com.arkkod.guvercin", 47 | "linux": { 48 | "target": [ 49 | "snap", 50 | "deb" 51 | ], 52 | "icon": "./build/" 53 | }, 54 | "mac": { 55 | "target": [ 56 | "dmg" 57 | ], 58 | "icon": "./images/logo.png" 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Welcome to Guvercin REST API Client 👋

2 |

3 | Version 4 | 5 | License: MIT 6 | 7 |

8 | 9 | > Guvercin is Open Source Rest API Client App. Simple, fast and minimal desktop and web application for developers. Better than postman :) 10 | 11 | ## Install and Usage 12 | 13 | 14 | Get it from the Snap Store 15 | 16 | 17 | ```sh 18 | git clone https://github.com/orcuntuna/guvercin.git 19 | cd guvercin 20 | npm install 21 | npm start 22 | ``` 23 | 24 | ## Screenshots 25 | 26 | ![Guvercin App Request and Response](images/screenshot/mac_ss_1.png) 27 | ![Guvercin App Response Details](images/screenshot/mac_ss_2.png) 28 | ![Guvercin App Headers Auto Complate](images/screenshot/mac_ss_3.png) 29 | ![Guvercin App Templates (light)](images/screenshot/mac_ss_4.png) 30 | ![Guvercin App Collection and History](images/screenshot/mac_ss_5.png) 31 | 32 | 33 | ## Author 34 | 35 | 👤 **Orçun Tuna** 36 | 37 | * Website: https://www.arkkod.com/ 38 | * Twitter: [@tunaorcun\_](https://twitter.com/tunaorcun\_) 39 | * Github: [@orcuntuna](https://github.com/orcuntuna) 40 | 41 | 👤 **Murat Ahmet Korkmaz** 42 | 43 | * Website: https://www.ahmetkorkmaz3.github.io/ 44 | * Twitter: [@ahmetmkorkmaz](https://twitter.com/ahmetmkorkmaz) 45 | * Github: [@ahmetkorkmaz3](https://github.com/ahmetkorkmaz3) 46 | 47 | ## Show your support 48 | 49 | Give a ⭐️ if this project helped you! 50 | 51 | 52 | 53 | 54 | 55 | ## 📝 License 56 | 57 | Copyright © 2020 [Orcun Tuna](https://github.com/orcuntuna).
58 | This project is [MIT](https://opensource.org/licenses/MIT) licensed. 59 | 60 | *** 61 | _This README was generated with ❤️ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_ 62 | -------------------------------------------------------------------------------- /renderers/history.js: -------------------------------------------------------------------------------- 1 | function create_history_template(index, method, url) { 2 | return ` 3 | 4 |
  • 5 | ` + method + ` 6 | ` + url + ` 7 |
  • 8 |
    `; 9 | } 10 | 11 | function method_colors(method){ 12 | var colors = { 13 | "get": "#10ac84", 14 | "post": "#2e86de", 15 | "put": "#f0932b", 16 | "delete": "#ee5253", 17 | "patch": "#be2edd", 18 | "custom": "#535c68" 19 | } 20 | method = method.toLowerCase(); 21 | if(colors[method]){ 22 | return colors[method]; 23 | } 24 | return colors["custom"]; 25 | } 26 | 27 | $(function () { 28 | 29 | user_history = db.get("history").value(); 30 | 31 | if (user_history.length > 0) { 32 | user_history.forEach((element, index) => { 33 | history_template = create_history_template(index, element.request_method, element.request_url); 34 | $("#history .list-group").prepend(history_template); 35 | }); 36 | } 37 | 38 | $("#history").on("click", ".list-group a", function(e) { 39 | history_index = $(this).attr("historyIndex"); 40 | 41 | history_request = user_history[history_index]; 42 | history_request_headers = history_request.request_headers; 43 | history_request_parameters = history_request.request_parameters; 44 | 45 | $("#url").val(history_request.request_url); 46 | $('#method-select option:selected').removeAttr('selected'); 47 | $("#method-select option[value='" + history_request.request_method +"']").attr("selected", "selected"); 48 | body_editor.setValue(history_request.request_body); 49 | history_request_headers.forEach(element => { 50 | element = JSON.parse(element); 51 | $("#tab-headers .header-list").html(""); 52 | $("#tab-headers .header-list").append(create_header_template(element.key, element.value)); 53 | }); 54 | $("#tab-headers .header-list").append(create_header_template()); 55 | 56 | 57 | history_request_parameters.forEach(element => { 58 | element = JSON.parse(element); 59 | $("#tab-params .param-list").html(""); 60 | $("#tab-params .param-list").append(create_parameter_template(element.key, element.value)); 61 | }); 62 | $("#tab-params .param-list").append(create_parameter_template()); 63 | body_editor.clearSelection(); 64 | 65 | 66 | }); 67 | }); -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const { app, BrowserWindow, Menu, shell, ipcMain, ipcRenderer, clipboard } = require('electron'); 2 | 3 | let win; 4 | 5 | const isMac = process.platform === 'darwin' 6 | 7 | function createWindow () { 8 | win = new BrowserWindow({ 9 | width: 800, 10 | height: 600, 11 | webPreferences: { 12 | nodeIntegration: true 13 | }, 14 | icon: __dirname + "/build/64x64.png" 15 | }); 16 | win.loadFile('pages/home.html') 17 | win.maximize(); 18 | win.on('closed', () => { 19 | win = null 20 | }); 21 | 22 | const template = [ 23 | { 24 | label: "File", 25 | submenu: [ 26 | { 27 | label: "About " + app.name , 28 | role: "about", 29 | }, 30 | { 31 | label: "Reload Application", 32 | accelerator: "CmdOrCtrl+R", 33 | click: () => { win.reload(); } 34 | }, 35 | { 36 | label: "Settings", 37 | accelerator: "CmdOrCtrl+P", 38 | click: () => { 39 | win.webContents.send("toggle-settings"); 40 | } 41 | }, 42 | { 43 | label: "Quit", 44 | role: "quit", 45 | accelerator: "CmdOrCtrl+Q" 46 | } 47 | ] 48 | }, 49 | { 50 | label: "Edit", 51 | submenu: [ 52 | { label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" }, 53 | { label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" }, 54 | { label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" }, 55 | { label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" }, 56 | { label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" }, 57 | { label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" } 58 | ] 59 | }, 60 | { 61 | label: "Go", 62 | submenu: [ 63 | { 64 | label: "Toggle History", 65 | accelerator: "CmdOrCtrl+H", 66 | click: () => { 67 | win.webContents.send("toggle-history"); 68 | } 69 | }, 70 | { 71 | label: "Toggle Collection", 72 | accelerator: "CmdOrCtrl+T", 73 | click: () => { 74 | win.webContents.send("toggle-collection"); 75 | } 76 | }, 77 | { 78 | label: "Save Request", 79 | accelerator: "CmdOrCtrl+S", 80 | click: () => { 81 | win.webContents.send("save-request"); 82 | } 83 | }, 84 | { 85 | label: "Send Request", 86 | accelerator: "CmdOrCtrl+Return", 87 | click: () => { 88 | win.webContents.send("send-request"); 89 | } 90 | } 91 | ] 92 | }, 93 | { 94 | label: "Help", 95 | submenu: [ 96 | { 97 | label: "Documentation", 98 | click: () => { shell.openExternal("https://www.github.com/orcuntuna/guvercin") } 99 | }, 100 | { 101 | label: "Open Developer Tool", 102 | accelerator: "CmdOrCtrl+Shift+i", 103 | click: () => { win.webContents.openDevTools() } 104 | } 105 | ] 106 | } 107 | ]; 108 | 109 | const menu = Menu.buildFromTemplate(template); 110 | Menu.setApplicationMenu(menu) 111 | } 112 | 113 | 114 | app.on('ready', createWindow) 115 | 116 | app.on('window-all-closed', () => { 117 | if (process.platform !== 'darwin') { 118 | app.quit() 119 | } 120 | }); 121 | 122 | app.on('activate', () => { 123 | if (win === null) { 124 | createWindow() 125 | } 126 | }); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,linux,macos,windows,visualstudiocode 3 | # Edit at https://www.gitignore.io/?templates=node,linux,macos,windows,visualstudiocode 4 | 5 | ### Linux ### 6 | *~ 7 | 8 | # temporary files which can be created if a process still has a handle open of a deleted file 9 | .fuse_hidden* 10 | 11 | # KDE directory preferences 12 | .directory 13 | 14 | # Linux trash folder which might appear on any partition or disk 15 | .Trash-* 16 | 17 | # .nfs files are created when an open file is removed but is still being accessed 18 | .nfs* 19 | 20 | ### macOS ### 21 | # General 22 | .DS_Store 23 | .AppleDouble 24 | .LSOverride 25 | 26 | # Icon must end with two \r 27 | Icon 28 | 29 | # Thumbnails 30 | ._* 31 | 32 | # Files that might appear in the root of a volume 33 | .DocumentRevisions-V100 34 | .fseventsd 35 | .Spotlight-V100 36 | .TemporaryItems 37 | .Trashes 38 | .VolumeIcon.icns 39 | .com.apple.timemachine.donotpresent 40 | 41 | # Directories potentially created on remote AFP share 42 | .AppleDB 43 | .AppleDesktop 44 | Network Trash Folder 45 | Temporary Items 46 | .apdisk 47 | 48 | ### Node ### 49 | # Logs 50 | logs 51 | *.log 52 | npm-debug.log* 53 | yarn-debug.log* 54 | yarn-error.log* 55 | lerna-debug.log* 56 | 57 | # Diagnostic reports (https://nodejs.org/api/report.html) 58 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 59 | 60 | # Runtime data 61 | pids 62 | *.pid 63 | *.seed 64 | *.pid.lock 65 | 66 | # Directory for instrumented libs generated by jscoverage/JSCover 67 | lib-cov 68 | 69 | # Coverage directory used by tools like istanbul 70 | coverage 71 | *.lcov 72 | 73 | # nyc test coverage 74 | .nyc_output 75 | 76 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 77 | .grunt 78 | 79 | # Bower dependency directory (https://bower.io/) 80 | bower_components 81 | 82 | # node-waf configuration 83 | .lock-wscript 84 | 85 | # Compiled binary addons (https://nodejs.org/api/addons.html) 86 | build/Release 87 | 88 | # Dependency directories 89 | node_modules/ 90 | jspm_packages/ 91 | 92 | # TypeScript v1 declaration files 93 | typings/ 94 | 95 | # TypeScript cache 96 | *.tsbuildinfo 97 | 98 | # Optional npm cache directory 99 | .npm 100 | 101 | # Optional eslint cache 102 | .eslintcache 103 | 104 | # Optional REPL history 105 | .node_repl_history 106 | 107 | # Output of 'npm pack' 108 | *.tgz 109 | 110 | # Yarn Integrity file 111 | .yarn-integrity 112 | 113 | # dotenv environment variables file 114 | .env 115 | .env.test 116 | 117 | # parcel-bundler cache (https://parceljs.org/) 118 | .cache 119 | 120 | # next.js build output 121 | .next 122 | 123 | # nuxt.js build output 124 | .nuxt 125 | 126 | # rollup.js default build output 127 | dist/ 128 | 129 | # Uncomment the public line if your project uses Gatsby 130 | # https://nextjs.org/blog/next-9-1#public-directory-support 131 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 132 | # public 133 | 134 | # Storybook build outputs 135 | .out 136 | .storybook-out 137 | 138 | # vuepress build output 139 | .vuepress/dist 140 | 141 | # Serverless directories 142 | .serverless/ 143 | 144 | # FuseBox cache 145 | .fusebox/ 146 | 147 | # DynamoDB Local files 148 | .dynamodb/ 149 | 150 | # Temporary folders 151 | tmp/ 152 | temp/ 153 | 154 | ### VisualStudioCode ### 155 | .vscode/* 156 | !.vscode/settings.json 157 | !.vscode/tasks.json 158 | !.vscode/launch.json 159 | !.vscode/extensions.json 160 | 161 | ### VisualStudioCode Patch ### 162 | # Ignore all local history of files 163 | .history 164 | 165 | ### Windows ### 166 | # Windows thumbnail cache files 167 | Thumbs.db 168 | Thumbs.db:encryptable 169 | ehthumbs.db 170 | ehthumbs_vista.db 171 | 172 | # Dump file 173 | *.stackdump 174 | 175 | # Folder config file 176 | [Dd]esktop.ini 177 | 178 | # Recycle Bin used on file shares 179 | $RECYCLE.BIN/ 180 | 181 | # Windows Installer files 182 | *.cab 183 | *.msi 184 | *.msix 185 | *.msm 186 | *.msp 187 | 188 | # Windows shortcuts 189 | *.lnk 190 | 191 | # End of https://www.gitignore.io/api/node,linux,macos,windows,visualstudiocode 192 | 193 | ./db.json 194 | dist -------------------------------------------------------------------------------- /renderers/collection.js: -------------------------------------------------------------------------------- 1 | function create_collection_template(index, method, url) { 2 | return ` 3 | 4 |
  • 5 | ` + method + ` 6 | ` + url + ` 7 | 10 |
  • 11 |
    `; 12 | } 13 | 14 | ipcRenderer.on("save-request", function(event) { 15 | $("#save").click(); 16 | }) 17 | 18 | $(function () { 19 | user_collection = db.get("collection").value(); 20 | 21 | if (user_collection.length > 0) { 22 | user_collection.forEach((element, index) => { 23 | collection_template = create_collection_template(index, element.request_method, element.request_url); 24 | $("#collection .list-group").prepend(collection_template); 25 | }); 26 | } 27 | 28 | $("#collection").on("click", ".list-group-item button", function() { 29 | Swal.fire({ 30 | title: 'Are you sure?', 31 | text: "You won't be able to revert this!", 32 | showCancelButton: true, 33 | confirmButtonColor: '#d33', 34 | cancelButtonColor: '#aaa', 35 | confirmButtonText: 'Delete Collection', 36 | cancelButtonText: 'Cancel' 37 | }).then((result) => { 38 | if (result.value) { 39 | collection_item = $(this).parent().parent().attr("collectionIndex"); 40 | $(this).parent().parent().remove(); 41 | db.get("collection").remove(user_collection[collection_item]).write() 42 | } 43 | }); 44 | 45 | 46 | }); 47 | 48 | 49 | $("#save").on("click", function() { 50 | 51 | method = $("#method-select").val(); 52 | url = $("#url").val(); 53 | body = body_editor.getValue(); 54 | 55 | if (url) { 56 | collection_data = { 57 | request_method: method, 58 | request_url: url, 59 | request_body: body, 60 | request_parameters: [], 61 | request_headers: [] 62 | }; 63 | 64 | $("#tab-headers .header-list .item").each(function(index){ 65 | if($(this).find(".params_key").val()){ 66 | var key = $(this).find(".params_key").val(); 67 | var value = $(this).find(".params_value").val(); 68 | collection_data.request_headers[index] = JSON.stringify({key: key, value: value}); 69 | } 70 | }); 71 | 72 | $("#tab-params .param-list .item").each(function(index){ 73 | if($(this).find(".params_key").val()){ 74 | var key = $(this).find(".params_key").val(); 75 | var value = $(this).find(".params_value").val(); 76 | collection_data.request_parameters[index] = JSON.stringify({key: key, value: value}); 77 | } 78 | }); 79 | 80 | last_collection = db.get("collection").value(); 81 | 82 | if (JSON.stringify(last_collection[last_collection.length - 1]) != JSON.stringify(collection_data)) { 83 | db.get("collection").push(collection_data).write(); 84 | collection_template = create_collection_template(last_collection.length-1, collection_data.request_method, collection_data.request_url); 85 | $("#collection .list-group").prepend(collection_template); 86 | 87 | Swal.fire({ 88 | icon: "success", 89 | title: "Good Job!", 90 | text: "Saving succesfully", 91 | }); 92 | } 93 | } else { 94 | Swal.fire({ 95 | icon: "error", 96 | title: "ERROR", 97 | text: "URL could not empty. Please enter URL", 98 | }); 99 | } 100 | 101 | }); 102 | 103 | $("#collection").on("click", ".list-group a", function(e) { 104 | collection_index = $(this).attr("collectionIndex"); 105 | 106 | collection_request = user_collection[collection_index]; 107 | collection_request_headers = collection_request.request_headers; 108 | collection_request_parameters = collection_request.request_parameters; 109 | 110 | $("#url").val(collection_request.request_url); 111 | $('#method-select option:selected').removeAttr('selected'); 112 | $("#method-select option[value='" + collection_request.request_method +"']").attr("selected", "selected"); 113 | body_editor.setValue(collection_request.request_body); 114 | collection_request_headers.forEach(element => { 115 | element = JSON.parse(element); 116 | $("#tab-headers .header-list").html(""); 117 | $("#tab-headers .header-list").append(create_header_template(element.key, element.value)); 118 | }); 119 | if (collection_request_headers.length > 0) { 120 | $("#tab-headers .header-list").append(create_header_template()); 121 | } 122 | 123 | 124 | collection_request_parameters.forEach(element => { 125 | element = JSON.parse(element); 126 | $("#tab-params .param-list").html(""); 127 | $("#tab-params .param-list").append(create_parameter_template(element.key, element.value)); 128 | }); 129 | if (collection_request_parameters.length > 0) { 130 | $("#tab-params .param-list").append(create_parameter_template()); 131 | } 132 | body_editor.clearSelection(); 133 | }); 134 | 135 | 136 | }); 137 | -------------------------------------------------------------------------------- /styles/home.css: -------------------------------------------------------------------------------- 1 | *{ 2 | outline: 0 !important; 3 | } 4 | 5 | body{ 6 | font-family: 'Lato', sans-serif; 7 | font-size: 15px; 8 | background: #fff;; 9 | } 10 | 11 | input, button, select, a{ 12 | box-shadow: none !important; 13 | } 14 | 15 | .logo{ 16 | color: #3d3d3d; 17 | font-weight: 700; 18 | } 19 | 20 | .request-bar{ 21 | background: #fafbfc; 22 | } 23 | 24 | .top{ 25 | width: 100%; 26 | height: 8px; 27 | background: #12c2e9; /* fallback for old browsers */ 28 | background: -webkit-linear-gradient(to right, #fb8817, #ff4b01, #c12127, #e02aff); /* Chrome 10-25, Safari 5.1-6 */ 29 | background: linear-gradient(to right, #fb8817, #ff4b01, #c12127, #e02aff); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ 30 | } 31 | 32 | .navbar{ 33 | box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); 34 | transition: all 0.3s cubic-bezier(.25,.8,.25,1); 35 | } 36 | 37 | .navbar .nav .nav-item a{ 38 | color: #333; 39 | padding: .5rem 0.7rem; 40 | } 41 | 42 | #request-alert{ 43 | display: none; 44 | } 45 | 46 | .custom-tabs{ 47 | display: flex; 48 | background: #fafbfc; 49 | margin-left: -15px; 50 | margin-right: -15px; 51 | padding-left: 15px; 52 | padding-right: 15px; 53 | } 54 | 55 | .custom-tabs .nav-item{ 56 | /*flex: 1;*/ 57 | text-align: center; 58 | } 59 | 60 | .custom-tabs .nav-link{ 61 | border: 0; 62 | border: 1px solid transparent; 63 | border-top: 3px solid transparent; 64 | border-radius: 3px 3px 0 0; 65 | padding-left: 20px; 66 | padding-right: 20px; 67 | color: #586069; 68 | } 69 | 70 | .custom-tabs .nav-link i{ 71 | margin-right: 6px; 72 | } 73 | 74 | .custom-tabs .nav-link.active{ 75 | border-color: #e36209 #e1e4e8 transparent; 76 | color: #24292e; 77 | } 78 | 79 | 80 | #props .tabs .tab{ 81 | display: none; 82 | padding-top: 20px; 83 | } 84 | 85 | #response .tabs .tab{ 86 | display: none; 87 | padding-top: 20px; 88 | } 89 | 90 | .header-list .item, 91 | .param-list .item{ 92 | display: flex; 93 | flex-direction: row; 94 | margin-bottom: 8px; 95 | position: relative; 96 | } 97 | 98 | .header-list .item .key, 99 | .param-list .item .key{ 100 | flex: 1; 101 | margin-right: 10px; 102 | } 103 | 104 | .header-list .item .value, 105 | .param-list .item .value{ 106 | flex: 2; 107 | } 108 | 109 | .header-list .item .operation, 110 | .param-list .item .operation{ 111 | display: flex; 112 | justify-content: center; 113 | align-items: center; 114 | } 115 | 116 | .header-list .item .operation button, 117 | .param-list .item .operation button{ 118 | height: auto; 119 | border: none; 120 | padding: .3rem .7rem; 121 | } 122 | 123 | .header-list .item input[type="text"], 124 | .param-list .item input[type="text"]{ 125 | height: auto; 126 | padding: .325rem .5rem; 127 | font-size: 15px; 128 | border-radius: 3px; 129 | font-weight: 400; 130 | } 131 | 132 | .header-list .item input[type="text"]::placeholder, 133 | .param-list .item input[type="text"]::placeholder{ 134 | font-weight: 400; 135 | color: #a0a0a0; 136 | } 137 | 138 | #send{ 139 | color: #fff; 140 | background: #0984e3; 141 | } 142 | 143 | #save{ 144 | color: #fff; 145 | background: #636e72; 146 | } 147 | 148 | .operation{ 149 | position: absolute; 150 | right: 14px; 151 | top: 5px; 152 | } 153 | 154 | .btn-delete{ 155 | padding: 0 !important; 156 | margin: 0; 157 | color: #a0a0a0; 158 | } 159 | 160 | .btn-delete:hover{ 161 | transition: 0.4s; 162 | color: #d63031; 163 | } 164 | 165 | #method-select{ 166 | background-color: #f9f9f9; 167 | } 168 | 169 | #body-editor { 170 | margin: auto; 171 | width: 100%; 172 | } 173 | 174 | #drawer, 175 | #history, 176 | #collection { 177 | width: 25%; 178 | min-width: 300px; 179 | height: calc(100vh - 64px); 180 | position: absolute; 181 | right: 0; 182 | top: 64px; 183 | background: #ffffff; 184 | z-index: 100; 185 | box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); 186 | display: none; 187 | overflow-y: auto; 188 | padding: 20px; 189 | } 190 | 191 | #history, 192 | #collection { 193 | width: 30%; 194 | min-width: 400px; 195 | display: none; 196 | } 197 | 198 | .close-drawer{ 199 | display: none; 200 | } 201 | 202 | .delete_param{ 203 | z-index: 10; 204 | } 205 | 206 | .delete_header{ 207 | z-index: 10; 208 | } 209 | 210 | #response-headers{ 211 | margin: 0; 212 | } 213 | 214 | .list-group a { 215 | text-decoration: none; 216 | } 217 | 218 | .list-group-item { 219 | display: flex; 220 | } 221 | 222 | .list-group a .list-group-item span.method { 223 | color: green; 224 | text-transform: uppercase; 225 | font-weight: bold; 226 | } 227 | 228 | .list-group a .list-group-item span.url { 229 | word-break: break-all; 230 | color: #333; 231 | } 232 | 233 | 234 | @media (min-width: 576px) and (max-width: 991px) { 235 | #response { 236 | margin-top: 10px; 237 | } 238 | } 239 | 240 | .response-code{ 241 | margin-left: auto; 242 | display: flex; 243 | justify-content: center; 244 | align-items: center; 245 | } 246 | 247 | .response-code .badge{ 248 | display: none; 249 | padding: 8px 10px; 250 | font-size: 14px; 251 | color: #fff; 252 | } 253 | 254 | .response-code .badge{ 255 | font-weight: bold; 256 | } 257 | 258 | .response-hr{ 259 | display: none; 260 | } 261 | 262 | .delete-button { 263 | border: none; 264 | background-color: transparent; 265 | color: #a0a0a0; 266 | margin-left: auto; 267 | } 268 | 269 | .delete-button:hover { 270 | color: #d63031; 271 | } 272 | 273 | .header-label { 274 | font-weight: bold; 275 | margin-bottom: 8px; 276 | } 277 | 278 | #tab-response-data { 279 | position: relative; 280 | } 281 | 282 | .loading { 283 | position: absolute; 284 | top: 50%; 285 | left: 50%; 286 | font-weight: bold; 287 | font-size: 20px; 288 | } -------------------------------------------------------------------------------- /renderers/settings.js: -------------------------------------------------------------------------------- 1 | ipcRenderer.on("toggle-history", function (event) { 2 | toggleHistory(); 3 | }); 4 | 5 | ipcRenderer.on("toggle-collection", function(event) { 6 | toggleCollection(); 7 | }); 8 | 9 | ipcRenderer.on("toggle-settings", function(event) { 10 | if ($("#drawer").is(":visible")) { 11 | $(".close-drawer a").click(); 12 | } else { 13 | $(".open-drawer a").click(); 14 | } 15 | }); 16 | 17 | function toggleHistory() { 18 | if ($("#drawer").is(":visible")) { 19 | $("#drawer").hide(); 20 | $(".close-drawer").hide(); 21 | $(".open-drawer").show(); 22 | } 23 | if ($("#collection").is(":visible")) { 24 | $("#collection").hide(); 25 | } 26 | $("#history").toggle(); 27 | } 28 | 29 | function toggleCollection() { 30 | if ($("#drawer").is(":visible")) { 31 | $("#drawer").hide(); 32 | $(".close-drawer").hide(); 33 | $(".open-drawer").show(); 34 | } 35 | if ($("#history").is(":visible")) { 36 | $("#history").hide(); 37 | } 38 | $("#collection").toggle(); 39 | } 40 | 41 | 42 | $(".open-drawer a").on("click", function (e) { 43 | e.preventDefault(); 44 | if ($("#history").is(":visible")) { 45 | $("#history").hide(); 46 | } 47 | if ($("#collection").is(":visible")) { 48 | $("#collection").hide(); 49 | } 50 | $("#drawer").show(); 51 | $(".open-drawer").hide(); 52 | $(".close-drawer").show(); 53 | }); 54 | 55 | $(".close-drawer a").on("click", function (e) { 56 | e.preventDefault(); 57 | $("#drawer").hide(); 58 | $(".close-drawer").hide(); 59 | $(".open-drawer").show(); 60 | }); 61 | 62 | $(".toggle-history a").on("click", function (e) { 63 | e.preventDefault(); 64 | toggleHistory(); 65 | }); 66 | 67 | $(".toggle-collection a").on("click", function (e) { 68 | e.preventDefault(); 69 | toggleCollection(); 70 | }); 71 | 72 | function setHeaderContentType(header_mode) { 73 | if (header_mode) { 74 | var changed = false; 75 | $("#tab-headers .header-list .item").each(function (index) { 76 | if ($(this).find(".params_key").val() == "Content-Type") { 77 | if (!changed) { 78 | $(this).find(".params_value").val(header_mode); 79 | changed = true; 80 | } 81 | } 82 | }); 83 | if (!changed) { 84 | var created = false; 85 | $("#tab-headers .header-list .item").each(function (index) { 86 | if (!$(this).find(".params_key").val()) { 87 | if (!created) { 88 | $(this).find(".params_key").val("Content-Type"); 89 | $(this).find(".params_value").val(header_mode); 90 | created = true; 91 | } 92 | } 93 | }); 94 | if (!created) { 95 | $("#tab-headers .header-list").append(header_template); 96 | $("#tab-headers .header-list .item:last").find(".params_key").val("Content-Type"); 97 | $("#tab-headers .header-list .item:last").find(".params_value").val(header_mode); 98 | } 99 | } 100 | } 101 | } 102 | 103 | function setDefaultAceOption(user_ace_option) { 104 | $('#ace-option option:selected').removeAttr('selected'); 105 | $("#ace-option option[value='" + user_ace_option +"']").attr("selected", "selected"); 106 | } 107 | 108 | function setAceOption(user_ace_option) { 109 | $('#body-content-type option:selected').removeAttr('selected'); 110 | $("#body-content-type option[value='" + user_ace_option + "']").attr("selected", "selected"); 111 | } 112 | 113 | function setAceThemeOption(theme_option) { 114 | $('#body-editor-theme option:selected').removeAttr('selected'); 115 | $("#body-editor-theme option[value='" + theme_option + "']").attr("selected", "selected"); 116 | } 117 | 118 | $(function () { 119 | 120 | user_theme = window.localStorage.getItem("theme"); 121 | 122 | user_ace_option = window.localStorage.getItem("ace_mode"); 123 | 124 | if (user_theme == "dark") { 125 | $("#theme-link").attr("href", "../styles/dark-theme.css"); 126 | body_editor.setTheme(require('ace-builds/src/theme-tomorrow_night_eighties')); 127 | response_editor.setTheme(require('ace-builds/src/theme-tomorrow_night_eighties')); 128 | $('#theme option:selected').removeAttr('selected'); 129 | $("#theme option[value='" + user_theme + "']").attr("selected", "selected"); 130 | setAceThemeOption("dark"); 131 | } 132 | 133 | 134 | $("#theme").on("change", function () { 135 | current_theme = window.localStorage.getItem("theme"); 136 | 137 | theme_option = $(this).children("option:selected").val(); 138 | 139 | if (theme_option != current_theme) { 140 | if (theme_option == "dark") { 141 | $("#theme-link").attr("href", "../styles/dark-theme.css"); 142 | window.localStorage.setItem("theme", "dark"); 143 | body_editor.setTheme(require('ace-builds/src/theme-tomorrow_night_eighties')); 144 | response_editor.setTheme(require('ace-builds/src/theme-tomorrow_night_eighties')); 145 | setAceThemeOption("dark"); 146 | } 147 | else if (theme_option == "light") { 148 | $("#theme-link").attr("href", "../styles/empty.css"); 149 | window.localStorage.setItem("theme", "light"); 150 | body_editor.setTheme(require('ace-builds/src/theme-xcode')); 151 | response_editor.setTheme(require('ace-builds/src/theme-xcode')); 152 | setAceThemeOption("light"); 153 | } 154 | } 155 | }); 156 | 157 | switch (user_ace_option) { 158 | case "json": 159 | mode = require("ace-builds/src/mode-json").Mode; 160 | new_header_mode = "application/json"; 161 | setDefaultAceOption(user_ace_option); 162 | setAceOption(user_ace_option); 163 | body_editor.session.setMode(new mode()); 164 | setHeaderContentType(new_header_mode); 165 | break; 166 | case "xml": 167 | mode = require("ace-builds/src/mode-xml").Mode; 168 | new_header_mode = "application/xml"; 169 | setDefaultAceOption(user_ace_option); 170 | setAceOption(user_ace_option); 171 | body_editor.session.setMode(new mode()); 172 | setHeaderContentType(new_header_mode); 173 | break; 174 | case "plain-text": 175 | mode = require("ace-builds/src/mode-plain_text").Mode; 176 | new_header_mode = "text/plain"; 177 | setDefaultAceOption(user_ace_option); 178 | setAceOption(user_ace_option); 179 | body_editor.session.setMode(new mode()); 180 | setHeaderContentType(new_header_mode); 181 | break; 182 | case "html": 183 | mode = require("ace-builds/src/mode-html").Mode; 184 | new_header_mode = "text/html"; 185 | setDefaultAceOption(user_ace_option); 186 | setAceOption(user_ace_option); 187 | body_editor.session.setMode(new mode()); 188 | setHeaderContentType(new_header_mode); 189 | break; 190 | } 191 | 192 | $("#ace-option").on("change", function () { 193 | current_option = window.localStorage.getItem("ace_mode"); 194 | ace_option = $(this).children("option:selected").val(); 195 | if (ace_option != current_option) { 196 | switch (ace_option) { 197 | case "json": 198 | mode = require("ace-builds/src/mode-json").Mode; 199 | new_header_mode = "application/json"; 200 | window.localStorage.setItem("ace_mode", "json"); 201 | setAceOption(ace_option); 202 | break; 203 | case "xml": 204 | mode = require("ace-builds/src/mode-xml").Mode; 205 | new_header_mode = "application/xml"; 206 | window.localStorage.setItem("ace_mode", "xml"); 207 | setAceOption(ace_option); 208 | break; 209 | case "plain-text": 210 | mode = require("ace-builds/src/mode-plain_text").Mode; 211 | new_header_mode = "text/plain"; 212 | window.localStorage.setItem("ace_mode", "plain-text"); 213 | setAceOption(ace_option); 214 | break; 215 | case "html": 216 | mode = require("ace-builds/src/mode-html").Mode; 217 | new_header_mode = "text/html"; 218 | window.localStorage.setItem("ace_mode", "html"); 219 | setAceOption(ace_option); 220 | break; 221 | } 222 | body_editor.session.setMode(new mode()); 223 | setHeaderContentType(new_header_mode); 224 | } 225 | }); 226 | }); 227 | -------------------------------------------------------------------------------- /pages/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Guvercin | REST API Client 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 | 20 |
    21 |
    22 | 23 | 27 |
    28 | 29 |
    30 | 31 | 37 |
    38 |
    39 | 40 |
    41 | 43 |
    44 | 45 |
    46 | 48 |
    49 | 50 | 73 | 74 |
    75 |
    76 |
    77 |
    78 |
    79 | 87 |
    88 | 89 |
    90 | 91 | 92 |
    93 |
    94 |
    95 |
    96 | 97 |
    98 | 99 | 102 |
    103 | 104 |
    105 | 106 |
    107 |
    108 |
    109 |
    110 |
    111 |
    112 | 123 |
    124 |
    125 |
    126 |
    127 |
    128 |
    129 |
    130 |
    131 |
    132 |
    133 |
    134 | 142 | 146 |
    147 |
    148 |
    149 |
    150 |
    151 |
    152 |
    153 |
    154 |
    155 |
    156 |
    157 |
    158 |
    159 |
    160 | 171 |
    172 |
    173 | 176 |
    177 |
    178 |
    179 |
      180 |
      181 |
        182 |
        183 |
        184 |
        185 |
        186 |
        187 |
        188 |
        189 |
        190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /renderers/send.js: -------------------------------------------------------------------------------- 1 | function validateURL(){ 2 | var url = $("#url").val(); 3 | if(url){ 4 | return true; 5 | } 6 | return false; 7 | } 8 | 9 | var response_codes = [ 10 | { code: 200, name: "OK", color: "#20bf6b" }, 11 | { code: 201, name: "Created", color: "#20bf6b" }, 12 | { code: 202, name: "Accepted", color: "#20bf6b" }, 13 | { code: 204, name: "No Content", color: "#20bf6b" }, 14 | { code: 301, name: "Moved Parmanently", color: "#4b6584" }, 15 | { code: 302, name: "Found", color: "#4b6584" }, 16 | { code: 303, name: "See Other", color: "#4b6584" }, 17 | { code: 304, name: "Not Modified", color: "#4b6584" }, 18 | { code: 307, name: "Temporary Redirect", color: "#4b6584" }, 19 | { code: 400, name: "Bad Request", color: "#eb3b5a" }, 20 | { code: 401, name: "Unauthorized", color: "#eb3b5a" }, 21 | { code: 403, name: "Forbidden", color: "#eb3b5a" }, 22 | { code: 404, name: "Not Found", color: "#eb3b5a" }, 23 | { code: 405, name: "Method Not Allowed", color: "#eb3b5a" }, 24 | { code: 406, name: "Not Acceptable", color: "#eb3b5a" }, 25 | { code: 412, name: "Precondition Failed", color: "#eb3b5a" }, 26 | { code: 415, name: "Unsupported Media Type", color: "#eb3b5a" }, 27 | { code: 500, name: "Internal Server Error", color: "#fa8231" }, 28 | { code: 501, name: "Not Implemented", color: "#fa8231" }, 29 | ] 30 | 31 | var response_timer; 32 | var response_time; 33 | 34 | ipcRenderer.on("send-request", function(event) { 35 | $("#request-form").submit(); 36 | }); 37 | 38 | $(function(){ 39 | 40 | var params = { 41 | url: null, 42 | method: null, 43 | body: null, 44 | headers: {}, 45 | params: "" 46 | } 47 | 48 | $("#request-form").on("submit", function(e){ 49 | e.preventDefault(); 50 | $("#send").attr("disabled", "disabled"); 51 | $("#loading").show(); 52 | $("#response-editor").hide(); 53 | if(validateURL()){ 54 | 55 | params.url = $("#url").val(); 56 | params.method = $("#method-select").val(); 57 | params.body = body_editor.getValue(); 58 | 59 | history_data = { 60 | request_method: params.method, 61 | request_url: params.url, 62 | request_body: params.body, 63 | request_parameters: [], 64 | request_headers: [] 65 | }; 66 | 67 | $("#tab-headers .header-list .item").each(function(index){ 68 | if($(this).find(".params_key").val()){ 69 | var key = $(this).find(".params_key").val(); 70 | var value = $(this).find(".params_value").val(); 71 | params.headers[key] = value; 72 | history_data.request_headers[index] = JSON.stringify({key: key, value: value}); 73 | } 74 | }); 75 | 76 | $("#tab-params .param-list .item").each(function(index){ 77 | if($(this).find(".params_key").val()){ 78 | var key = $(this).find(".params_key").val(); 79 | var value = $(this).find(".params_value").val(); 80 | if(index == 0){ 81 | params.params += "?" + key + "=" + value; 82 | }else{ 83 | params.params += "&" + key + "=" + value; 84 | } 85 | history_data.request_parameters[index] = JSON.stringify({key: key, value: value}); 86 | 87 | } 88 | }); 89 | 90 | if(params.method.toLowerCase() == "get"){ 91 | delete params.body; 92 | } 93 | 94 | var response = {} 95 | 96 | response_time = 0; 97 | response_timer = setInterval(() => { 98 | response_time += 10; 99 | }, 10); 100 | 101 | fetch(params.url + params.params, params).then(res => { 102 | response.headers = res.headers.raw(); 103 | response.status = res.status; 104 | response.statusText = res.statusText; 105 | return res.text(); 106 | }).then(data => { 107 | 108 | clearInterval(response_timer); 109 | $("#send").removeAttr("disabled"); 110 | $("#loading").hide(); 111 | $("#response-editor").show(); 112 | 113 | /* History Save */ 114 | last_history = db.get("history").value(); 115 | 116 | if (last_history.length > 0) { 117 | if (JSON.stringify(last_history[last_history.length - 1]) != JSON.stringify(history_data)) { 118 | history_template = create_history_template(last_history.length, history_data.request_method, history_data.request_url); 119 | $("#history .list-group").prepend(history_template); 120 | } 121 | } else { 122 | history_template = create_history_template(last_history.length, history_data.request_method, history_data.request_url); 123 | $("#history .list-group").prepend(history_template); 124 | } 125 | db.get('history') 126 | .push(history_data) 127 | .write() 128 | /* History Save */ 129 | 130 | response.data = data; 131 | console.log(response); 132 | 133 | if(response.headers["content-type"][0].includes("json")){ 134 | try{ 135 | response.data = JSON.stringify(JSON.parse(response.data), null, 4); 136 | }catch(err){ 137 | console.log(err); 138 | } 139 | } 140 | 141 | if(response.headers["content-type"][0].includes("xml")){ 142 | try{ 143 | var pretty_xml = xml_beautify(response.data); 144 | response.data = pretty_xml; 145 | response.data = response.data.replace(/^\s*\n/gm, ""); 146 | }catch(err){ 147 | console.log(err); 148 | } 149 | } 150 | 151 | response_editor.setValue(response.data); 152 | response_editor.clearSelection(); 153 | 154 | var mode = null; 155 | if(response.headers["content-type"][0].includes("json")){ 156 | mode = require("ace-builds/src/mode-json").Mode; 157 | }else if(response.headers["content-type"][0].includes("xml")){ 158 | mode = require("ace-builds/src/mode-xml").Mode; 159 | }else if(response.headers["content-type"][0].includes("html")){ 160 | mode = require("ace-builds/src/mode-html").Mode; 161 | }else{ 162 | mode = require("ace-builds/src/mode-plain_text").Mode; 163 | } 164 | 165 | response_editor.session.setMode(new mode()); 166 | 167 | $("#response-headers").html(""); 168 | $("#response-info").html(""); 169 | $("#response-info").append('
      • Response Time: '+response_time / 1000+' seconds
      • '); 170 | Object.keys(response.headers).forEach(function(key) { 171 | $("#response-headers").append('
      • '+key+': '+response.headers[key]+'
      • '); 172 | }); 173 | 174 | response_codes.forEach(element => { 175 | if(element.code == response.status){ 176 | $("#response-info").prepend('
      • Response Code: '+element.code+' ('+element.name+')
      • '); 177 | $(".response-code span").css("background-color", element.color); 178 | $(".response-code span").text(element.code + " (" + element.name + ")"); 179 | $(".response-code span").show(); 180 | } 181 | }); 182 | 183 | if(response.data.length > 0){ 184 | var response_size = (new TextEncoder().encode(response.data)).length; 185 | $("#response-info").append('
      • Response Data Size: '+response_size / 1000+' kb
      • '); 186 | } 187 | 188 | $(".response-hr").show(); 189 | 190 | }).catch(err => { 191 | clearInterval(response_timer); 192 | $("#send").removeAttr("disabled"); 193 | $("#loading").hide(); 194 | $("#response-editor").show(); 195 | console.log(err); 196 | response_editor.setValue(""); 197 | $("#response-headers").html(""); 198 | $("#response-info").html(""); 199 | $(".response-hr").hide(); 200 | $(".response-code span").css("background-color", "#eb3b5a"); 201 | $(".response-code span").text(err.code); 202 | $(".response-code span").show(); 203 | }); 204 | 205 | }else{ 206 | $("#send").removeAttr("disabled"); 207 | $("#loading").hide(); 208 | $("#response-editor").show(); 209 | $("#request-alert span.message").html("Hata! Girdğiniz istek adresi geçerli bir URL değil."); 210 | $("#request-alert").show() 211 | } 212 | }); 213 | 214 | $("#request-alert button").on("click", function(e){ 215 | e.preventDefault(); 216 | $("#request-alert").hide(); 217 | }); 218 | 219 | }); -------------------------------------------------------------------------------- /renderers/request.js: -------------------------------------------------------------------------------- 1 | function create_parameter_template(key="", value=""){ 2 | return ` 3 |
        4 |
        5 | 6 |
        7 |
        8 | 9 |
        10 |
        11 | 12 |
        13 |
        ` 14 | } 15 | 16 | function create_header_template(key = "", value = "") { 17 | return ` 18 |
        19 |
        20 | 21 |
        22 |
        23 | 24 |
        25 |
        26 | 27 |
        28 |
        `; 29 | } 30 | 31 | var headerKeySuggests = ["Connection","Keep-Alive","Proxy-Authenticate","Proxy-Authorization","TE","Trailer","Transfer-Encoding","Upgrade","Connection","WWW-Authenticate","Authorization","Proxy-Authenticate","Proxy-Authorization","Age","Cache-Control","Clear-Site-Data","Expires","Pragma","Warning","Accept-CH","Accept-CH-Lifetime","Early-Data","Content-DPR","DPR","Device-Memory","Save-Data","Viewport-Width","Width","Last-Modified","ETag","If-Modified-Since","If-Unmodified-Since","ETag","If-Match","If-None-Match","If-Match","If-None-Match","If-Modified-Since","If-Unmodified-Since","Vary","Connection","Keep-Alive","Accept","Accept-Charset","Accept-Encoding","Accept-Language","Expect","Max-Forwards","Cookie","2Set-Cookie","Cookie2","Set-Cookie2","Cookie","Set-Cookie2","Set-Cookie","Access-Control-Allow-Origin","Access-Control-Allow-Credentials","Access-Control-Allow-Headers","Access-Control-Allow-Methods","Access-Control-Expose-Headers","Access-Control-Max-Age","Access-Control-Request-Headers","Access-Control-Request-Method","Origin","Timing-Allow-Origin","DNT","Tk","Content-Disposition","Content-Length","Content-Type","Content-Encoding","Content-Language","Content-Location","Forwarded","X-Forwarded-For","X-Forwarded-Host","X-Forwarded-Proto","Via","Location","From","Host","Referer","Referrer-Policy","Referer","User-Agent","Allow","Server","Accept-Ranges","Range","If-Range","Content-Range","Cross-Origin-Embedder-Policy","Cross-Origin-Opener-Policy","Cross-Origin-Resource-Policy","Content-Security-Policy","Content-Security-Policy-Report-Only","Expect-CT","Feature-Policy","Public-Key-Pins","Public-Key-Pins-Report-Only","Strict-Transport-Security","Upgrade-Insecure-Requests","upgrade-insecure-requests","X-Content-Type-Options","X-Download-Options","X-Frame-Optionsy","X-Permitted-Cross-Domain-Policies","X-Powered-By","X-XSS-Protection","Last-Event-ID","NEL","Ping-From","Ping-To","Report-To","Transfer-Encoding","TE","Trailer","Sec-WebSocket-Key","Sec-WebSocket-Extensions","Sec-WebSocket-Accept","Sec-WebSocket-Protocol","Sec-WebSocket-Version","Accept-Push-Policy","Accept-Signature","Alt-Svc","Date","Large-Allocation","Link","Push-Policy","Retry-After","Signature","Signed-Headers","Server-Timing","Service-Worker-Allowed","SourceMap","Upgrade","X-DNS-Prefetch-Control","X-Firefox-Spdy","X-Pingback","X-Requested-With","X-Robots-Tag","X-UA-Compatible"]; 32 | var headerValueSuggests = ["application/EDI-X12","application/EDIFACT","application/javascript","application/octet-stream","application/ogg","application/pdf","application/xhtml+xml","application/x-shockwave-flash","application/json","application/ld+json","application/xml","application/zip","application/x-www-form-urlencoded","audio/mpeg","audio/x-ms-wma","audio/vnd.rn-realaudio","audio/x-wav","image/gif","image/jpeg","image/png","image/tiff","image/vnd.microsoft.icon","image/x-icon","image/vnd.djvu","image/svg+xml","multipart/mixed","multipart/alternative","multipart/related (using by MHTML (HTML mail).)","multipart/form-data","text/css","text/csv","text/html","text/javascript (obsolete)","text/plain","text/xml","video/mpeg","video/mp4","video/quicktime","video/x-ms-wmv","video/x-msvideo","video/x-flv","video/webm","application/vnd.oasis.opendocument.text","application/vnd.oasis.opendocument.spreadsheet","application/vnd.oasis.opendocument.presentation","application/vnd.oasis.opendocument.graphics","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-powerpoint","application/vnd.openxmlformats-officedocument.presentationml.presentation","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.mozilla.xul+xml"]; 33 | 34 | function checkParamsAndAdd(){ 35 | var params = $("#tab-params .param-list input.params_key"); 36 | if($(params[params.length-1]).val()){ 37 | $("#tab-params .param-list").append(create_parameter_template()); 38 | } 39 | } 40 | 41 | function checkHeadersAndAdd() { 42 | var header = $("#tab-headers .header-list input.params_key"); 43 | if ($(header[header.length-1]).val()) { 44 | $("#tab-headers .header-list").append(create_header_template()); 45 | } 46 | $("#tab-headers .params_key").autocomplete({ 47 | source: [headerKeySuggests] 48 | }); 49 | 50 | $("#tab-headers .params_value").autocomplete({ 51 | source: [headerValueSuggests] 52 | }); 53 | $(".xdsoft_autocomplete_hint").attr("tabindex", "-1"); 54 | } 55 | 56 | $(function(){ 57 | 58 | var active_tab_name_props = $("#props .nav-tabs .active").attr("tab"); 59 | $("#props .tabs .tab[tab='"+active_tab_name_props+"']").show(); 60 | 61 | var active_tab_name_response = $("#response .nav-tabs .active").attr("tab"); 62 | $("#response .tabs .tab[tab='"+active_tab_name_response+"']").show(); 63 | 64 | $("#tab-params .param-list").append(create_parameter_template()); 65 | $("#tab-params .param-list").append(create_parameter_template()); 66 | $("#tab-params .param-list").append(create_parameter_template()); 67 | $("#tab-headers .header-list").append(create_header_template()); 68 | $("#tab-headers .header-list").append(create_header_template()); 69 | $("#tab-headers .header-list").append(create_header_template()); 70 | 71 | $("#tab-headers .params_key").autocomplete({ 72 | source: [headerKeySuggests] 73 | }); 74 | 75 | $("#tab-headers .params_value").autocomplete({ 76 | source: [headerValueSuggests] 77 | }); 78 | 79 | $(".xdsoft_autocomplete_hint").attr("tabindex", "-1"); 80 | 81 | $("#tab-params .param-list").on("change", "input.params_key", function(e){ 82 | checkParamsAndAdd(); 83 | }); 84 | 85 | $("#tab-headers .header-list").on("change", "input.params_key", function(e){ 86 | checkHeadersAndAdd(); 87 | }); 88 | 89 | body_editor = ace.edit("body-editor", { 90 | minLines: 15, 91 | maxLines: 9999 92 | }); 93 | 94 | var JSONMode = require("ace-builds/src/mode-json").Mode; 95 | body_editor.session.setMode(new JSONMode()); 96 | body_editor.setTheme(require('ace-builds/src/theme-xcode')); 97 | body_editor.setFontSize("14px"); 98 | 99 | $("#body-editor-theme").on("change", function(e){ 100 | switch ($("#body-editor-theme").val()) { 101 | case "light": 102 | body_editor.setTheme(require('ace-builds/src/theme-xcode')); 103 | response_editor.setTheme(require('ace-builds/src/theme-xcode')); 104 | break; 105 | case "dark": 106 | body_editor.setTheme(require('ace-builds/src/theme-tomorrow_night_eighties')); 107 | response_editor.setTheme(require('ace-builds/src/theme-tomorrow_night_eighties')); 108 | break; 109 | default: 110 | break; 111 | } 112 | }); 113 | 114 | $("#body-content-type").on("change", function(e){ 115 | var mode; 116 | var new_header_mode; 117 | switch ($("#body-content-type").val()) { 118 | case "json": 119 | mode = require("ace-builds/src/mode-json").Mode; 120 | new_header_mode = "application/json"; 121 | break; 122 | case "xml": 123 | mode = require("ace-builds/src/mode-xml").Mode; 124 | new_header_mode = "application/xml"; 125 | break; 126 | case "plain text": 127 | mode = require("ace-builds/src/mode-plain_text").Mode; 128 | new_header_mode = "text/plain"; 129 | break; 130 | case "html": 131 | mode = require("ace-builds/src/mode-html").Mode; 132 | new_header_mode = "text/html"; 133 | break; 134 | default: 135 | mode = require("ace-builds/src/mode-plain_text").Mode; 136 | break; 137 | } 138 | body_editor.session.setMode(new mode()); 139 | if(new_header_mode){ 140 | var changed = false; 141 | $("#tab-headers .header-list .item").each(function(index){ 142 | if($(this).find(".params_key").val() == "Content-Type"){ 143 | if(!changed){ 144 | $(this).find(".params_value").val(new_header_mode); 145 | changed = true; 146 | } 147 | } 148 | }); 149 | if(!changed){ 150 | var created = false; 151 | $("#tab-headers .header-list .item").each(function(index){ 152 | if(!$(this).find(".params_key").val()){ 153 | if(!created){ 154 | $(this).find(".params_key").val("Content-Type"); 155 | $(this).find(".params_value").val(new_header_mode); 156 | created = true; 157 | } 158 | } 159 | }); 160 | if(!created){ 161 | $("#tab-headers .header-list").append(create_header_template()); 162 | $("#tab-headers .header-list .item:last").find(".params_key").val("Content-Type"); 163 | $("#tab-headers .header-list .item:last").find(".params_value").val(new_header_mode); 164 | } 165 | } 166 | } 167 | }); 168 | 169 | $("#method-select").on("change", async function(e){ 170 | if($("#method-select").val() == "custom"){ 171 | const { value: method } = await Swal.fire({ 172 | title: 'Create Custom Method', 173 | input: 'text', 174 | inputPlaceholder: 'Enter your custom method name', 175 | showCancelButton: true 176 | }); 177 | if (method) { 178 | $("#method-select").append(''); 179 | $("#method-select option:last").attr("selected", "selected"); 180 | } 181 | } 182 | }); 183 | 184 | $("#method-list a").on("click", function(e){ 185 | e.preventDefault(); 186 | }); 187 | 188 | $("#props .nav-tabs .nav-item a").on("click", function(e){ 189 | e.preventDefault(); 190 | $("#props .nav-link").removeClass("active"); 191 | $(this).addClass("active"); 192 | var tab_name = $(this).attr("tab"); 193 | $("#props .tabs .tab").hide(); 194 | $("#props .tabs .tab[tab='"+tab_name+"']").show(); 195 | }); 196 | 197 | $("#response .nav-tabs .nav-item a").on("click", function(e){ 198 | e.preventDefault(); 199 | $("#response .nav-link").removeClass("active"); 200 | $(this).addClass("active"); 201 | var tab_name = $(this).attr("tab"); 202 | $("#response .tabs .tab").hide(); 203 | $("#response .tabs .tab[tab='"+tab_name+"']").show(); 204 | }); 205 | 206 | $("#tab-params .param-list").on("click", ".add_param", function(e){ 207 | $("#tab-params .param-list").append(create_parameter_template()); 208 | }); 209 | 210 | $("#tab-params .param-list").on("click", ".delete_param", function(e){ 211 | if($("#tab-params .param-list .item").length > 1){ 212 | if($(this).parent().parent().find(".params_key").val()){ 213 | Swal.fire({ 214 | title: 'Are you sure?', 215 | text: "You won't be able to revert this!", 216 | showCancelButton: true, 217 | confirmButtonColor: '#d33', 218 | cancelButtonColor: '#aaa', 219 | confirmButtonText: 'Delete Parameter', 220 | cancelButtonText: 'Cancel' 221 | }).then((result) => { 222 | if (result.value) { 223 | $(this).parent().parent().remove(); 224 | } 225 | }); 226 | }else{ 227 | $(this).parent().parent().remove(); 228 | } 229 | }else{ 230 | Swal.fire("Warning", "You cant delete last parameter, maybe you need it.", "warning"); 231 | } 232 | }); 233 | 234 | $("#tab-headers .header-list").on("click", ".delete_header", function(e){ 235 | if($("#tab-headers .header-list .item").length > 1){ 236 | if($(this).parent().parent().find(".params_key").val()){ 237 | Swal.fire({ 238 | title: 'Are you sure?', 239 | text: "You won't be able to revert this!", 240 | showCancelButton: true, 241 | confirmButtonColor: '#d33', 242 | cancelButtonColor: '#aaa', 243 | confirmButtonText: 'Delete Parameter', 244 | cancelButtonText: 'Cancel' 245 | }).then((result) => { 246 | if (result.value) { 247 | $(this).parent().parent().remove(); 248 | } 249 | }); 250 | }else{ 251 | $(this).parent().parent().remove(); 252 | } 253 | }else{ 254 | Swal.fire("Warning", "You cant delete last header, maybe you need it.", "warning"); 255 | } 256 | }); 257 | 258 | }); --------------------------------------------------------------------------------