Skip to content

Commit

Permalink
add copy as curl (#769)
Browse files Browse the repository at this point in the history
* add copy as curl

* fix copy error when security context not safe

* add decode

* delete_is_decode_in_frontend_api

* change notice

* fix icon size, icon notice, clipboard

* optimize curl content

* optimize curl content of jsonstring

* optimize curl content of jsonstring

* notice word

* fix review feedback

* add /api/flow/{id} raw param

* chenge deal logic of unknow content-type

* change notice

* change param name

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* test unit test failed

* delete item bottom 2px

---------

Co-authored-by: wujiasheng03 <noO0oOo0ob>
  • Loading branch information
noO0oOo0ob authored Jul 28, 2023
1 parent 67fbf5d commit ebdd997
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 3 deletions.
6 changes: 6 additions & 0 deletions frontend/src/api/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ export const getFlowDetail = (flowId) => {
})
}

export const getFlowDetailOrigin = (flowId) => {
return axios({
url: '/api/flow/' + flowId + "?is_origin=true"
})
}

export const getFlowList = () => {
return axios({
url: '/api/flow'
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/store/inspector.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as api from '@/api'
import { bus } from '@/eventbus'
import {generateCurl} from '@/utils'

export default {
state: {
Expand Down Expand Up @@ -75,6 +76,10 @@ export default {
return
}
state.selectedFlowFilter = selectedFlowFilterName
},
generateAndCopyCurl(state, requestData){
let cmd = generateCurl(requestData)
bus.$emit('clipboard', cmd)
}
},
actions: {
Expand Down Expand Up @@ -188,6 +193,15 @@ export default {
.catch(error => {
bus.$emit('msg.error', 'Delete flow error: ' + error.data.message)
})
},
getFlowDetailForCmd ({state, commit}, flowId) {
api.getFlowDetailOrigin(flowId)
.then(response => {
commit('generateAndCopyCurl', response.data.data.request)
})
.catch(error => {
bus.$emit('msg.error', 'Get flow detail error: ' + error.data.message)
})
}
}
}
63 changes: 63 additions & 0 deletions frontend/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { bus } from '@/eventbus'

export const readablizeBytes = (bytes) => {
if(bytes===0){
return '0 B'
Expand Down Expand Up @@ -31,3 +33,64 @@ export const timestampToDatetime = (timeStamp) => {
let second = (dateObj.getSeconds() < 10 ? '0'+dateObj.getSeconds() : dateObj.getSeconds())
return month + '/' + date + ' ' + hour + ':' + minute + ':' + second
}

export const generateCurl = (requestData) => {
let contentType = requestData['headers']['Content-Type'] || ''
let curl = ['curl ' + generateCurlUrl(requestData['url'])]
curl = curl.concat(generateCurlMethod(requestData['method']))
curl = curl.concat(generateCurlHeader(requestData['headers']))
curl = curl.concat(generateCurlData(requestData['data'], contentType))
return curl.join(' \\\n ')
}

function generateCurlUrl (url) {
return `-g \"${url}\"`
}

function generateCurlMethod (method) {
return ['-X '+method]
}

function generateCurlHeader (headers) {
let ignoreKey = [
'Host',
'Accept-Encoding'
]
let headerStrList = []
for(let key in headers){
if(!ignoreKey.includes(key))
headerStrList.push(`-H \"${key}:${headers[key]}\"`)
}
return headerStrList
}

function generateCurlData (data, dataType) {
if(typeof data === 'undefined' || !data){
return []
}
let dataStrList = []
if(!dataType){
dataStrList.push(`--data-raw \'${generateJsonString(data)}\'`)
}else if(dataType.includes('application/json')){
dataStrList.push(`-d \'${generateJsonString(data)}\'`)
}else if(dataType.includes('application/x-www-form-urlencoded')){
dataStrList = Object.entries(data).map(([key, value]) => `-d \"${key}=${data[key]}\"`)
}else{
bus.$emit('msg.error', `Generate curl param -d failed: Lyrebird doesn't support ContentType of ${dataType}`)
}
return dataStrList
}

function generateJsonString (data) {
let res = ''
if(typeof data === 'string'){
return data.trim()
}else{
try{
res = JSON.stringify(data)
}catch(e){
bus.$emit('msg.error', `Generate curl param -d failed: Data type conversion failed`)
}
}
return res
}
9 changes: 9 additions & 0 deletions frontend/src/views/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,15 @@ export default {
this.$bus.$off('msg.info', this.infoMessage)
this.$bus.$off('msg.error', this.errorMessage)
this.$bus.$off('msg.destroy', this.destroyMessage)
this.$bus.$off('clipboard', this.copyToClipboard)
},
created() {
this.$bus.$on('msg.success', this.successMessage)
this.$bus.$on('msg.loading', this.loadingMessage)
this.$bus.$on('msg.info', this.infoMessage)
this.$bus.$on('msg.error', this.errorMessage)
this.$bus.$on('msg.destroy', this.destroyMessage)
this.$bus.$on('clipboard', this.copyToClipboard)
this.$io.on('statusBarUpdate', this.loadAllStatusList)
this.$io.on('datamanagerUpdate', this.loadDataMap)
this.$io.on('msgSuccess', this.successMessage)
Expand Down Expand Up @@ -198,6 +200,13 @@ export default {
destroyMessage() {
this.$Message.destroy()
},
copyToClipboard(text) {
this.$copyText(text).then(e => {
this.$bus.$emit('msg.success', 'Copy Success')
}, e => {
this.$bus.$emit('msg.error', 'Copy Failed')
})
}
},
}
</script>
Expand Down
28 changes: 26 additions & 2 deletions frontend/src/views/inspector/FlowList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@

<v-spacer/>

<span class="flow-list-item-copy-btn" @click.stop>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<span v-bind="attrs" v-on="on">
<v-btn
icon
x-small
plain
@click="generateCurlUrl(item)"
>
<v-icon
x-small
color="accent"
>mdi-xml</v-icon>
</v-btn>
</span>
</template>
Copy as cURL
</v-tooltip>
</span>

<span class="flow-list-item-copy-btn" @click.stop>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
Expand All @@ -132,7 +153,7 @@
</v-btn>
</span>
</template>
Copy
Copy Url
</v-tooltip>

</span>
Expand Down Expand Up @@ -380,6 +401,9 @@ export default {
}
return row.response.mock
},
generateCurlUrl(item){
this.$store.dispatch('getFlowDetailForCmd', item.id)
},
onUrlCopy () {
this.$bus.$emit('msg.success', 'URL copied!')
},
Expand Down Expand Up @@ -493,7 +517,7 @@ export default {
display: inline-block;
word-break: keep-all;
max-width: 900px;
width: calc(100% - 50px);
width: calc(100% - 100px);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
Expand Down
6 changes: 5 additions & 1 deletion lyrebird/mock/blueprints/apis/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ class Flow(Resource):

def get(self, id):
is_decode = request.args.get('is_decode', 'false').strip().lower() == 'true'
is_origin = request.args.get('is_origin', 'false').strip().lower() == 'true'
for item in context.application.cache.items():
if item['id'] == id:
# Import decoder for decoding the requested content
display_item = {}
application.encoders_decoders.decoder_handler(item, output=display_item)
if is_origin:
display_item.update(item)
else:
application.encoders_decoders.decoder_handler(item, output=display_item)
if is_decode:
display_item['request'] = deepcopy(display_item['request'])
for key in ('url', 'path', 'query'):
Expand Down

0 comments on commit ebdd997

Please sign in to comment.