mirror of
https://github.com/fjogeleit/http-request-action.git
synced 2024-12-23 04:37:28 +00:00
Merge pull request #37 from Atlas-Authority/master
Support single file upload
This commit is contained in:
commit
d45f6649f6
8 changed files with 86 additions and 12 deletions
7
.github/workflows/test.yml
vendored
7
.github/workflows/test.yml
vendored
|
@ -61,3 +61,10 @@ jobs:
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
data: '{ "key": "value" }'
|
data: '{ "key": "value" }'
|
||||||
files: '{ "file": "${{ github.workspace }}/testfile.txt" }'
|
files: '{ "file": "${{ github.workspace }}/testfile.txt" }'
|
||||||
|
|
||||||
|
- name: Request Postman Echo POST single file
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
url: 'https://postman-echo.com/post'
|
||||||
|
method: 'POST'
|
||||||
|
file: "${{ github.workspace }}/testfile.txt"
|
||||||
|
|
|
@ -26,6 +26,7 @@ jobs:
|
||||||
|contentType | Request ContentType| application/json |
|
|contentType | Request ContentType| application/json |
|
||||||
|data | Request Body Content:<br>- text content like JSON or XML<br>- key=value pairs separated by '&' and contentType: application/x-www-form-urlencoded<br><br>only for POST / PUT / PATCH Requests | '{}' |
|
|data | Request Body Content:<br>- text content like JSON or XML<br>- key=value pairs separated by '&' and contentType: application/x-www-form-urlencoded<br><br>only for POST / PUT / PATCH Requests | '{}' |
|
||||||
|files | Map of key / absolute file paths send as multipart/form-data request to the API, if set the contentType is set to multipart/form-data, values provided by data will be added as additional FormData values, nested objects are not supported. **Example provided in the _test_ Workflow of this Action** | '{}' |
|
|files | Map of key / absolute file paths send as multipart/form-data request to the API, if set the contentType is set to multipart/form-data, values provided by data will be added as additional FormData values, nested objects are not supported. **Example provided in the _test_ Workflow of this Action** | '{}' |
|
||||||
|
|file | Single absolute file path send as `application/octet-stream` request to the API, if set the contentType is set to `application/octet-stream`. This input will be ignored if either `data` or `files` input is present. **Example provided in the _test_ Workflow of this Action** ||
|
||||||
|timeout| Request Timeout in ms | 5000 (5s) |
|
|timeout| Request Timeout in ms | 5000 (5s) |
|
||||||
|username| Username for Basic Auth ||
|
|username| Username for Basic Auth ||
|
||||||
|password| Password for Basic Auth ||
|
|password| Password for Basic Auth ||
|
||||||
|
|
|
@ -19,6 +19,9 @@ inputs:
|
||||||
description: 'Map of absolute file paths as JSON String'
|
description: 'Map of absolute file paths as JSON String'
|
||||||
required: false
|
required: false
|
||||||
default: '{}'
|
default: '{}'
|
||||||
|
file:
|
||||||
|
description: 'A single absolute file path'
|
||||||
|
required: false
|
||||||
username:
|
username:
|
||||||
description: 'Auth Username'
|
description: 'Auth Username'
|
||||||
required: false
|
required: false
|
||||||
|
|
40
dist/index.js
vendored
40
dist/index.js
vendored
|
@ -1909,6 +1909,7 @@ const METHOD_POST = 'POST'
|
||||||
* @param {{ baseURL: string; timeout: number; headers: { [name: string]: string } }} param0.instanceConfig
|
* @param {{ baseURL: string; timeout: number; headers: { [name: string]: string } }} param0.instanceConfig
|
||||||
* @param {string} param0.data Request Body as string, default {}
|
* @param {string} param0.data Request Body as string, default {}
|
||||||
* @param {string} param0.files Map of Request Files (name: absolute path) as JSON String, default: {}
|
* @param {string} param0.files Map of Request Files (name: absolute path) as JSON String, default: {}
|
||||||
|
* @param {string} param0.file Single request file (absolute path)
|
||||||
* @param {{ username: string; password: string }|undefined} param0.auth Optional HTTP Basic Auth
|
* @param {{ username: string; password: string }|undefined} param0.auth Optional HTTP Basic Auth
|
||||||
* @param {*} param0.actions
|
* @param {*} param0.actions
|
||||||
* @param {number[]} param0.ignoredCodes Prevent Action to fail if the API response with one of this StatusCodes
|
* @param {number[]} param0.ignoredCodes Prevent Action to fail if the API response with one of this StatusCodes
|
||||||
|
@ -1917,7 +1918,7 @@ const METHOD_POST = 'POST'
|
||||||
*
|
*
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const request = async({ method, instanceConfig, data, files, auth, actions, ignoredCodes, preventFailureOnNoResponse, escapeData }) => {
|
const request = async({ method, instanceConfig, data, files, file, auth, actions, ignoredCodes, preventFailureOnNoResponse, escapeData }) => {
|
||||||
try {
|
try {
|
||||||
if (escapeData) {
|
if (escapeData) {
|
||||||
data = data.replace(/"[^"]*"/g, (match) => {
|
data = data.replace(/"[^"]*"/g, (match) => {
|
||||||
|
@ -1930,8 +1931,8 @@ const request = async({ method, instanceConfig, data, files, auth, actions, igno
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files && files !== '{}') {
|
if (files && files !== '{}') {
|
||||||
filesJson = convertToJSON(files)
|
let filesJson = convertToJSON(files)
|
||||||
dataJson = convertToJSON(data)
|
let dataJson = convertToJSON(data)
|
||||||
|
|
||||||
if (Object.keys(filesJson).length > 0) {
|
if (Object.keys(filesJson).length > 0) {
|
||||||
try {
|
try {
|
||||||
|
@ -1944,6 +1945,12 @@ const request = async({ method, instanceConfig, data, files, auth, actions, igno
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only consider file if neither data nor files provided
|
||||||
|
if ((!data || data === '{}') && (!files || files === '{}') && file) {
|
||||||
|
data = fs.createReadStream(file)
|
||||||
|
updateConfigForFile(instanceConfig, file, actions)
|
||||||
|
}
|
||||||
|
|
||||||
const requestData = {
|
const requestData = {
|
||||||
auth,
|
auth,
|
||||||
method,
|
method,
|
||||||
|
@ -2041,6 +2048,30 @@ const updateConfig = async (instanceConfig, formData, actions) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param instanceConfig
|
||||||
|
* @param filePath
|
||||||
|
* @param {*} actions
|
||||||
|
*
|
||||||
|
* @returns {{ baseURL: string; timeout: number; headers: { [name: string]: string } }}
|
||||||
|
*/
|
||||||
|
const updateConfigForFile = (instanceConfig, filePath, actions) => {
|
||||||
|
try {
|
||||||
|
const { size } = fs.statSync(filePath)
|
||||||
|
|
||||||
|
return {
|
||||||
|
...instanceConfig,
|
||||||
|
headers: {
|
||||||
|
...instanceConfig.headers,
|
||||||
|
'Content-Length': size,
|
||||||
|
'Content-Type': 'application/octet-stream'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(error) {
|
||||||
|
actions.setFailed({ message: `Unable to read Content-Length: ${error.message}`, data, files })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {FormData} formData
|
* @param {FormData} formData
|
||||||
*
|
*
|
||||||
|
@ -4898,6 +4929,7 @@ const instanceConfig = {
|
||||||
|
|
||||||
const data = core.getInput('data') || '{}';
|
const data = core.getInput('data') || '{}';
|
||||||
const files = core.getInput('files') || '{}';
|
const files = core.getInput('files') || '{}';
|
||||||
|
const file = core.getInput('file')
|
||||||
const method = core.getInput('method') || METHOD_POST;
|
const method = core.getInput('method') || METHOD_POST;
|
||||||
const preventFailureOnNoResponse = core.getInput('preventFailureOnNoResponse') === 'true';
|
const preventFailureOnNoResponse = core.getInput('preventFailureOnNoResponse') === 'true';
|
||||||
const escapeData = core.getInput('escapeData') === 'true';
|
const escapeData = core.getInput('escapeData') === 'true';
|
||||||
|
@ -4909,7 +4941,7 @@ if (typeof ignoreStatusCodes === 'string' && ignoreStatusCodes.length > 0) {
|
||||||
ignoredCodes = ignoreStatusCodes.split(',').map(statusCode => parseInt(statusCode.trim()))
|
ignoredCodes = ignoreStatusCodes.split(',').map(statusCode => parseInt(statusCode.trim()))
|
||||||
}
|
}
|
||||||
|
|
||||||
request({ data, method, instanceConfig, auth, preventFailureOnNoResponse, escapeData, files, ignoredCodes, actions: new GithubActions() })
|
request({ data, method, instanceConfig, auth, preventFailureOnNoResponse, escapeData, files, file, ignoredCodes, actions: new GithubActions() })
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -1,12 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "http-request-action",
|
"name": "http-request-action",
|
||||||
"version": "1.8.0",
|
"version": "1.9.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "http-request-action",
|
"version": "1.9.0",
|
||||||
"version": "1.8.0",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zeit/ncc": "^0.22",
|
"@zeit/ncc": "^0.22",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "http-request-action",
|
"name": "http-request-action",
|
||||||
"version": "1.8.2",
|
"version": "1.9.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"private": false,
|
"private": false,
|
||||||
|
|
|
@ -11,6 +11,7 @@ const METHOD_POST = 'POST'
|
||||||
* @param {{ baseURL: string; timeout: number; headers: { [name: string]: string } }} param0.instanceConfig
|
* @param {{ baseURL: string; timeout: number; headers: { [name: string]: string } }} param0.instanceConfig
|
||||||
* @param {string} param0.data Request Body as string, default {}
|
* @param {string} param0.data Request Body as string, default {}
|
||||||
* @param {string} param0.files Map of Request Files (name: absolute path) as JSON String, default: {}
|
* @param {string} param0.files Map of Request Files (name: absolute path) as JSON String, default: {}
|
||||||
|
* @param {string} param0.file Single request file (absolute path)
|
||||||
* @param {{ username: string; password: string }|undefined} param0.auth Optional HTTP Basic Auth
|
* @param {{ username: string; password: string }|undefined} param0.auth Optional HTTP Basic Auth
|
||||||
* @param {*} param0.actions
|
* @param {*} param0.actions
|
||||||
* @param {number[]} param0.ignoredCodes Prevent Action to fail if the API response with one of this StatusCodes
|
* @param {number[]} param0.ignoredCodes Prevent Action to fail if the API response with one of this StatusCodes
|
||||||
|
@ -19,7 +20,7 @@ const METHOD_POST = 'POST'
|
||||||
*
|
*
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const request = async({ method, instanceConfig, data, files, auth, actions, ignoredCodes, preventFailureOnNoResponse, escapeData }) => {
|
const request = async({ method, instanceConfig, data, files, file, auth, actions, ignoredCodes, preventFailureOnNoResponse, escapeData }) => {
|
||||||
try {
|
try {
|
||||||
if (escapeData) {
|
if (escapeData) {
|
||||||
data = data.replace(/"[^"]*"/g, (match) => {
|
data = data.replace(/"[^"]*"/g, (match) => {
|
||||||
|
@ -32,8 +33,8 @@ const request = async({ method, instanceConfig, data, files, auth, actions, igno
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files && files !== '{}') {
|
if (files && files !== '{}') {
|
||||||
filesJson = convertToJSON(files)
|
let filesJson = convertToJSON(files)
|
||||||
dataJson = convertToJSON(data)
|
let dataJson = convertToJSON(data)
|
||||||
|
|
||||||
if (Object.keys(filesJson).length > 0) {
|
if (Object.keys(filesJson).length > 0) {
|
||||||
try {
|
try {
|
||||||
|
@ -46,6 +47,12 @@ const request = async({ method, instanceConfig, data, files, auth, actions, igno
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only consider file if neither data nor files provided
|
||||||
|
if ((!data || data === '{}') && (!files || files === '{}') && file) {
|
||||||
|
data = fs.createReadStream(file)
|
||||||
|
updateConfigForFile(instanceConfig, file, actions)
|
||||||
|
}
|
||||||
|
|
||||||
const requestData = {
|
const requestData = {
|
||||||
auth,
|
auth,
|
||||||
method,
|
method,
|
||||||
|
@ -143,6 +150,30 @@ const updateConfig = async (instanceConfig, formData, actions) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param instanceConfig
|
||||||
|
* @param filePath
|
||||||
|
* @param {*} actions
|
||||||
|
*
|
||||||
|
* @returns {{ baseURL: string; timeout: number; headers: { [name: string]: string } }}
|
||||||
|
*/
|
||||||
|
const updateConfigForFile = (instanceConfig, filePath, actions) => {
|
||||||
|
try {
|
||||||
|
const { size } = fs.statSync(filePath)
|
||||||
|
|
||||||
|
return {
|
||||||
|
...instanceConfig,
|
||||||
|
headers: {
|
||||||
|
...instanceConfig.headers,
|
||||||
|
'Content-Length': size,
|
||||||
|
'Content-Type': 'application/octet-stream'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(error) {
|
||||||
|
actions.setFailed({ message: `Unable to read Content-Length: ${error.message}`, data, files })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {FormData} formData
|
* @param {FormData} formData
|
||||||
*
|
*
|
||||||
|
|
|
@ -36,6 +36,7 @@ const instanceConfig = {
|
||||||
|
|
||||||
const data = core.getInput('data') || '{}';
|
const data = core.getInput('data') || '{}';
|
||||||
const files = core.getInput('files') || '{}';
|
const files = core.getInput('files') || '{}';
|
||||||
|
const file = core.getInput('file')
|
||||||
const method = core.getInput('method') || METHOD_POST;
|
const method = core.getInput('method') || METHOD_POST;
|
||||||
const preventFailureOnNoResponse = core.getInput('preventFailureOnNoResponse') === 'true';
|
const preventFailureOnNoResponse = core.getInput('preventFailureOnNoResponse') === 'true';
|
||||||
const escapeData = core.getInput('escapeData') === 'true';
|
const escapeData = core.getInput('escapeData') === 'true';
|
||||||
|
@ -47,4 +48,4 @@ if (typeof ignoreStatusCodes === 'string' && ignoreStatusCodes.length > 0) {
|
||||||
ignoredCodes = ignoreStatusCodes.split(',').map(statusCode => parseInt(statusCode.trim()))
|
ignoredCodes = ignoreStatusCodes.split(',').map(statusCode => parseInt(statusCode.trim()))
|
||||||
}
|
}
|
||||||
|
|
||||||
request({ data, method, instanceConfig, auth, preventFailureOnNoResponse, escapeData, files, ignoredCodes, actions: new GithubActions() })
|
request({ data, method, instanceConfig, auth, preventFailureOnNoResponse, escapeData, files, file, ignoredCodes, actions: new GithubActions() })
|
||||||
|
|
Loading…
Reference in a new issue