본문 바로가기
Research/Google products

shootingstar_howto_Appscript에서 보낸 요청을 local nest.js 서버에서 ngrok으로 수신하기

by RIEM 2023. 4. 19.

https://www.oldbookillustrations.com/illustrations/shooting-star/

 

배경

Google Appscript 스케쥴러를 만드는 중이다. 일종의 AWS Lambda 대용인데, google sheet의 스크래핑 함수를 이용하기 때문에 기능상 문제는 없고 오히려 구현이 편하다고 생각한다.

이렇게 스크래핑한 데이터를 nest.js 서버로 POST 요청으로 보내주고 싶은데, 문제는 현재 nest.js 서버가 로컬에서 구동중인데, 웹상에서 로컬로 HTTP 요청을 어떻게 하냐는 것이었다.

컴퓨터의 포트를 개방하고 IP 주소를 통해서 요청을 받을까 하다가, 커뮤니티의 한 분이 ngrok을 사용해보라고 권해주셔서 사용해보았다.

 

ngrok

ngrok은 외부에서 localhost로 접근할 수 있도록 localhost를 웹상에 띄어주는 도구다.

 

구현

웹상에서 회원가입 후 컴퓨터 운영체제에 맞는 파일을 다운받는다. 파일을 실행하면 complete라는 문구가 뜨면서 더 이상 진행되지 않는 stuck된 상황이 발생한다.

이 경우 파일의 디렉토리에 접근해서 아래 명령어를 쳐주면 된다. 3000은 3000번 포트를 개방한다는 의미다.

$ ./ngrok http 3000

 

위와 같이 명령어를 검색하면 로컬에 매핑되는 외부 ip 주소를 생성해준다. 이 주소로 쏴주면 된다. 그런데 이 주소는 일정 세션이 지나면 바뀐다고 한다. 이를 방지하기 위해 회원가입 시 발금해주는 토큰을 사용하면 되는 것 같다. 나는 당장 테스트만 하면 되었기에 토큰은 사용하지 않았다.

Insomnia로 외부 ngrok으로 호스팅된 웹 주소로 요청해보니, 로컬의 nest.js 서버가 잘 수신한 것을 볼 수 있다.

App Script

그렇다면 App Script에서 POST 요청을 해주는 코드를 짜주자.

function createSheetAndGetData() {

  // Variables
  const slack_url = <SLACK_WEBHOOK_URL>; 

  try {
    // create new sheet, naming with date string
    var name = (new Date()).toISOString().split('T')[0];
    SpreadsheetApp.getActiveSpreadsheet().insertSheet(name);

    // Google sheet
    const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
    const ss = spreadsheet.getSheetByName(name);

    var header_reuter = ss.getRange(1,1);
    header_reuter.setValue('Reuter');

    var scraping_reuter = ss.getRange(2, 1); // 2번째 행, 1번째 열
    scraping_reuter.setValue(`=IMPORTXML("https://www.reuters.com/world/","//a[@data-testid='Heading']")`);

    const datas_range_reuter = ss.getRange('A2:A30');
    const datas_reuter = datas_range_reuter.getValues(); // 2차 배열로 헤드라인 값들 반환
    const filtered_datas_reuter = datas_reuter.filter(el => el[0].length > 1)
    console.log(filtered_datas_reuter)

    // Send HTTP POST request to nest.js server
    var url = <url_local_machine_with_ngrok>;
var options = {
    "method": "post",
    // "headers": {
    //     "Authorization": "Basic " + Utilities.base64Encode(" ...account.SID... : ...auth.token... ")
    // },
    "payload": {
        "data": JSON.stringify(filtered_datas_reuter)
    }
};
var response = UrlFetchApp.fetch(url, options);

    // msg for SLACK
    let msg_reuter = "*Reuters*\n";
    // A2~A30 중 빈 셀은 제외하고 내용 추가
    filtered_datas_reuter.forEach(el => {
      msg_reuter += `- ${el}\n`
    })

    msg_reuter += `from Reuters(<https://www.reuters.com/world/>)`

    const params = {
      method: "post", 
      contentType: "application/json", 
      muteHttpExceptions: true, 
      payload: JSON.stringify({
        // "text 키값은 유지해주고, hello 메시지 내용반 바꿔주면 된다"
        "text": msg_reuter 
      }) 
    };

    const sendMsg = UrlFetchApp.fetch(slack_url, params)
    var respCode = sendMsg.getResponseCode()
    Logger.log(sendMsg)
    Logger.log(respCode)

  } catch (err) {
    Logger.log(err)

    // Send error msg to Slack
    const params = {
    method: "post", 
    contentType: "application/json", 
    muteHttpExceptions: true, 
    payload: JSON.stringify({
      "text": "[ERROR] something went wrong..."
    }) 
  };
  const sendMsg = UrlFetchApp.fetch(slack_url, params)
  } 
  

}

 

nest.js 서버에 잘 도착했다.

Reference

https://github.com/inconshreveable/ngrok/issues/627

https://yunwoong.tistory.com/131

댓글