mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-23 20:55:41 +00:00
fix(curl-parser): curl commands with url without protocol (#5453)
This commit is contained in:
@@ -312,7 +312,22 @@ const isURL = (arg) => {
|
||||
if (typeof arg !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return !!URL.parse(arg || '').host;
|
||||
|
||||
// First try to parse as a regular URL (with protocol)
|
||||
if (URL.parse(arg || '').host) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it looks like a domain without protocol
|
||||
// This regex matches domain patterns like:
|
||||
// - example.com
|
||||
// - sub.example.com
|
||||
// - example.com/path
|
||||
// - example.com/path?query=value
|
||||
// Must contain at least one dot to be considered a domain
|
||||
const DOMAIN_PATTERN = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(\/[^\s]*)?(\?[^\s]*)?$/;
|
||||
|
||||
return DOMAIN_PATTERN.test(arg);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -320,8 +335,9 @@ const isURL = (arg) => {
|
||||
* Handles shell-quote operator objects and query parameter patterns
|
||||
*/
|
||||
const isURLFragment = (arg) => {
|
||||
// If it's a glob pattern that looks like a URL, treat it as a complete URL
|
||||
if (arg && typeof arg === 'object' && arg.op === 'glob') {
|
||||
return !!URL.parse(arg.pattern || '').host;
|
||||
return isURL(arg.pattern);
|
||||
}
|
||||
if (arg && typeof arg === 'object' && arg.op === '&') {
|
||||
return true;
|
||||
@@ -341,7 +357,13 @@ const setURL = (request, url) => {
|
||||
const urlString = getUrlString(url);
|
||||
if (!urlString) return;
|
||||
|
||||
const newUrl = request.url ? request.url + urlString : urlString;
|
||||
// Add default protocol if none is present
|
||||
let processedUrl = urlString;
|
||||
if (!request.url && !urlString.match(/^[a-zA-Z]+:\/\//)) {
|
||||
processedUrl = 'https://' + urlString;
|
||||
}
|
||||
|
||||
const newUrl = request.url ? request.url + processedUrl : processedUrl;
|
||||
|
||||
const { url: formattedUrl, queries, urlWithoutQuery } = parseUrl(newUrl);
|
||||
|
||||
|
||||
@@ -438,6 +438,73 @@ describe('parseCurlCommand', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handling URLs without protocols', () => {
|
||||
it('should parse URL without protocol and default to https', () => {
|
||||
const result = parseCurlCommand(`
|
||||
curl echo.usebruno.com
|
||||
`);
|
||||
|
||||
expect(result).toEqual({
|
||||
method: 'get',
|
||||
url: 'https://echo.usebruno.com',
|
||||
urlWithoutQuery: 'https://echo.usebruno.com'
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse URL without protocol with path and query parameters', () => {
|
||||
const result = parseCurlCommand(`
|
||||
curl api.example.com/users?page=1&limit=10
|
||||
`);
|
||||
|
||||
expect(result).toEqual({
|
||||
method: 'get',
|
||||
url: 'https://api.example.com/users?page=1&limit=10',
|
||||
urlWithoutQuery: 'https://api.example.com/users',
|
||||
queries: [
|
||||
{ name: 'page', value: '1' },
|
||||
{ name: 'limit', value: '10' }
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse a complex curl command with multiple features and no protocol', () => {
|
||||
const result = parseCurlCommand(`
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer token123" \
|
||||
-H "X-Custom-Header: custom header" \
|
||||
-d '{"name": "John\\'s data", "email": "john@example.com", "message": "Don\\'t stop believing!", "path": "/home/user/file.txt", "json": {"nested": "value", "array": [1, 2, 3]}}' \
|
||||
-u "api_user:api_pass" \
|
||||
--compressed \
|
||||
api.example.com/v1/users?param1=value1¶m2=custom+param
|
||||
`);
|
||||
|
||||
expect(result).toEqual({
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer token123',
|
||||
'X-Custom-Header': 'custom header',
|
||||
'Accept-Encoding': 'deflate, gzip'
|
||||
},
|
||||
data: '{"name": "John\'s data", "email": "john@example.com", "message": "Don\'t stop believing!", "path": "/home/user/file.txt", "json": {"nested": "value", "array": [1, 2, 3]}}',
|
||||
auth: {
|
||||
mode: 'basic',
|
||||
basic: {
|
||||
username: 'api_user',
|
||||
password: 'api_pass'
|
||||
}
|
||||
},
|
||||
queries: [
|
||||
{ name: 'param1', value: 'value1' },
|
||||
{ name: 'param2', value: 'custom+param' }
|
||||
],
|
||||
url: 'https://api.example.com/v1/users?param1=value1¶m2=custom+param',
|
||||
urlWithoutQuery: 'https://api.example.com/v1/users'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle compressed flag', () => {
|
||||
const result = parseCurlCommand(`
|
||||
|
||||
Reference in New Issue
Block a user