@@ -49,6 +49,7 @@ const ToolStorageUpload: React.FC<ToolStorageUploadProps> = ({ onBack, editMode
4949 body_type : initialData ?. body_type || 'application/json' , // application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data, text/plain, text/html, text/csv, url-params
5050 is_query_string : initialData ?. is_query_string || false ,
5151 response_filter : initialData ?. response_filter || false ,
52+ html_parser : initialData ?. html_parser || false ,
5253 response_filter_path : initialData ?. response_filter_path || '' ,
5354 response_filter_field : initialData ?. response_filter_field || '' ,
5455 } ) ;
@@ -361,12 +362,47 @@ const ToolStorageUpload: React.FC<ToolStorageUploadProps> = ({ onBack, editMode
361362 const pathKeys = formData . response_filter_path . split ( '.' ) ;
362363
363364 for ( const key of pathKeys ) {
364- if ( extractedData && typeof extractedData === 'object' && key in extractedData ) {
365- extractedData = extractedData [ key ] ;
366- } else {
367- // 경로를 찾지 못하면 원본 반환
365+ if ( ! extractedData ) {
368366 return displayData ;
369367 }
368+
369+ // 배열 인덱스 처리: key[0], key[1] 등의 형식 지원
370+ const arrayMatch = key . match ( / ^ ( .+ ?) \[ ( \d + ) \] $ / ) ;
371+
372+ if ( arrayMatch ) {
373+ // 배열 접근: key[index] 형식
374+ const arrayKey = arrayMatch [ 1 ] ;
375+ const arrayIndex = parseInt ( arrayMatch [ 2 ] , 10 ) ;
376+
377+ if ( typeof extractedData === 'object' && arrayKey in extractedData ) {
378+ extractedData = extractedData [ arrayKey ] ;
379+ if ( Array . isArray ( extractedData ) && arrayIndex >= 0 && arrayIndex < extractedData . length ) {
380+ extractedData = extractedData [ arrayIndex ] ;
381+ } else {
382+ // 배열이 아니거나 인덱스가 범위를 벗어나면 원본 반환
383+ return displayData ;
384+ }
385+ } else {
386+ // key를 찾지 못하면 원본 반환
387+ return displayData ;
388+ }
389+ } else if ( / ^ \d + $ / . test ( key ) ) {
390+ // 순수 숫자인 경우 (배열 인덱스만)
391+ const index = parseInt ( key , 10 ) ;
392+ if ( Array . isArray ( extractedData ) && index >= 0 && index < extractedData . length ) {
393+ extractedData = extractedData [ index ] ;
394+ } else {
395+ return displayData ;
396+ }
397+ } else {
398+ // 일반 객체 키 접근
399+ if ( typeof extractedData === 'object' && key in extractedData ) {
400+ extractedData = extractedData [ key ] ;
401+ } else {
402+ // 경로를 찾지 못하면 원본 반환
403+ return displayData ;
404+ }
405+ }
370406 }
371407 }
372408
@@ -472,7 +508,8 @@ const ToolStorageUpload: React.FC<ToolStorageUploadProps> = ({ onBack, editMode
472508 body : formData . api_method !== 'GET' ? body : undefined ,
473509 staticBody : formData . api_method !== 'GET' ? staticBody : undefined ,
474510 bodyType : formData . body_type ,
475- isQueryString : formData . is_query_string
511+ isQueryString : formData . is_query_string ,
512+ htmlParser : formData . html_parser
476513 } ) ;
477514
478515 // 백엔드 프록시를 통해 API 테스트
@@ -484,6 +521,7 @@ const ToolStorageUpload: React.FC<ToolStorageUploadProps> = ({ onBack, editMode
484521 static_body : staticBody ,
485522 body_type : formData . body_type ,
486523 is_query_string : formData . is_query_string ,
524+ html_parser : formData . html_parser ,
487525 api_timeout : formData . api_timeout || 30
488526 } as any ) ;
489527
@@ -575,6 +613,7 @@ const ToolStorageUpload: React.FC<ToolStorageUploadProps> = ({ onBack, editMode
575613 api_timeout : formData . api_timeout ,
576614 is_query_string : formData . is_query_string ,
577615 response_filter : formData . response_filter ,
616+ html_parser : formData . html_parser ,
578617 response_filter_path : formData . response_filter_path ,
579618 response_filter_field : formData . response_filter_field ,
580619 status : apiTestSuccess ? 'active' : 'inactive' ,
@@ -1239,13 +1278,38 @@ const ToolStorageUpload: React.FC<ToolStorageUploadProps> = ({ onBack, editMode
12391278
12401279 { formData . response_filter && (
12411280 < >
1281+ < div className = { styles . formRow } >
1282+ < div >
1283+ < div className = { styles . fieldLabel } >
1284+ HTML Parser 사용
1285+ </ div >
1286+ < div className = { styles . fieldDescription } >
1287+ HTML 응답을 파싱하여 텍스트만 추출합니다.
1288+ </ div >
1289+ </ div >
1290+ < div className = { styles . fieldInput } >
1291+ < label className = { styles . checkboxLabel } >
1292+ < input
1293+ type = "checkbox"
1294+ name = "html_parser"
1295+ checked = { formData . html_parser }
1296+ onChange = { handleInputChange }
1297+ className = { styles . checkbox }
1298+ disabled = { loading }
1299+ />
1300+ < span > HTML Parser 활성화</ span >
1301+ </ label >
1302+ </ div >
1303+ </ div >
1304+
12421305 < div className = { styles . formRow } >
12431306 < div >
12441307 < div className = { styles . fieldLabel } >
12451308 필터 경로
12461309 </ div >
12471310 < div className = { styles . fieldDescription } >
1248- 응답 객체에서 데이터를 추출할 경로를 지정하세요. < br > </ br > (예: data.results)
1311+ 응답 객체에서 데이터를 추출할 경로를 지정하세요. < br > </ br >
1312+ (예: data.results, html.body.div[1], items[0].content)
12491313 </ div >
12501314 </ div >
12511315 < div className = { styles . fieldInput } >
@@ -1256,7 +1320,7 @@ const ToolStorageUpload: React.FC<ToolStorageUploadProps> = ({ onBack, editMode
12561320 value = { formData . response_filter_path }
12571321 onChange = { handleInputChange }
12581322 className = { styles . input }
1259- placeholder = "data.weather.current"
1323+ placeholder = "data.weather.current 또는 html.body.div[1] "
12601324 disabled = { loading }
12611325 />
12621326 </ div >
0 commit comments