DB로 브라우저 확장을 어떻게 Dropbox로 만들었는지

나는 재미있는 그림을 수집하고 채팅에서 사용하는 것을 좋아하기 때문에 크롬 확장을 구축하여 나의 생활을 완화시키기로 결정했다.다음 기능은 다음과 같습니다.
  • 컴퓨터에서 이미지 업로드
  • 특수 브라우저 상하문 메뉴를 클릭하여 이미지 업로드
  • 레이블을 이미지로 설정하고 검색
  • 이것은
    이것은a repo(냄새경보코드!)

    Dropbox API 액세스


    분명히 우리는 이러한 정보를 저장하기 위해 데이터베이스도 필요하고, 이미지를 업로드하기 위해 저장도 필요하다.그래서 나는 이미지와 데이터베이스를 JSON으로 일부 파일 위탁 관리 서비스 (Dropbox, OneDrive, Google Drive 등) 에 저장하기로 결정했다.
    이러한 서비스의 문서를 깊이 연구한 후에, 나는 그것들 중 대부분이 권한이 부여된 후에 사용자에게 방향을 바꿀 수 있는 공공 URL이 필요하다는 것을 깨달았다. 그리고 이 URL에는 그들의 API를 사용할 수 있는 영패가 포함될 것이다.이것은 브라우저 프로토콜을 기반으로 하는 크롬 extension://확장이 존재하기 때문에, 크롬 extension://는 분명히 지원되지 않습니다.
    그리고 나서 나는 Dropbox에 또 다른 사용자 인증 방식이 있다는 것을 발견했다.
    다음 URL만 열면 됩니다.https://www.dropbox.com/oauth2/authorize?response_type=code&client_id={{YOUR_APP_KEY}}
    응용 프로그램에 단독 폴더를 만들고 특수 코드가 있는 페이지를 열어 달라고 요청할 것입니다.

    이 코드를 응용 프로그램 암호와 함께 Dropbox API로 보내야 합니다.보답으로 새로 만든 폴더를 처리할 영패를 받을 것입니다.
    추출 부분은 매우 간단합니다. 이 페이지에 특수한 스크립트를 삽입하기만 하면 됩니다.이 점을 하기 위해서는 명세서에 그것을 정의해야 한다.json 파일:
     "content_scripts": [
        {
          "matches": ["https://www.dropbox.com/1/oauth2/authorize_submit"],
          "js": ["dropboxCodeExtractor.js"]
        }
      ],
    
    dropboxCodeExtractor.js:
    function getToken() {
      const tokenSelector = "[data-token]";
      const tokenAttr = "data-token";
      const element = document.querySelector(tokenSelector);
      if (element) {
        const code = element.getAttribute(tokenAttr);
        CommunicationService.authenticate(code);
      }
    }
    
    window.onload = getToken;
    
    
    이제 이 코드를 응용 프로그램 키와 함께 Dropbox API로 보내야 합니다.나는 확장 코드에서 직접 실행할 수 있지만, 이러한 상황에서 우리의 클라이언트 코드에 응용 프로그램 키가 하나 있을 것이다. 이것은 매우 나쁘다.그래서 간단한 lambda 함수를 만들기로 했습니다. 이 함수는 이 코드를 받아들여 Dropbox에 보내기로 했습니다. 프로그램 기밀이 포함되어 있습니다.다음은 코드입니다.
    const axios = require("axios");
    const URLSearchParams = require("url").URLSearchParams;
    
    exports.auth = async event => {
      let body = JSON.parse(event.body);
      const params = new URLSearchParams();
      params.append("grant_type", "authorization_code");
      params.append("code", body.code);
      params.append("client_id", process.env.DROPBOX_APP_KEY);
      params.append("client_secret", process.env.DROPBOX_APP_SECRET);
    
      try {
        let token = await axios
          .post("https://api.dropbox.com/oauth2/token", params, {
            headers: {
              "Content-Type": "application/x-www-form-urlencoded",
            },
          })
          .then(async response => {
            return response.data.access_token;
          });
        return {
          statusCode: 200,
          body: JSON.stringify({ token }),
        };
      } catch (error) {
        console.error(error);
        return {
          statusCode: 500,
          body: JSON.stringify({
            error: "Failed to get token",
          }),
        };
      }
    };
    
    
    다음은 차트의 전체 프로세스입니다.

    대단합니다. 이제 우리는 우리가 필요로 하는 모든 것을 올릴 수 있습니다.

    팝업과 백그라운드 스크립트 사이의 공유 상태


    모르는 사람들에게 확장은 대부분의 웹 응용 프로그램처럼 실행 중인 것만은 아니다.다음과 같은 기능이 있습니다.
  • 백그라운드 스크립트 - 백그라운드에서 실행되는 스크립트😀 또한 항상 유효합니다. (manfest. json에서 사용하지 않으면)
  • 팝업 스크립트 - 확장 아이콘
  • 을 클릭하면 팝업 창에서 실행되는 스크립트
  • 내용 스크립트 - 특정 페이지의 스크립트(예를 들어 위의 코드 추출 부분)를 직접 주입
  • 나는 Redux (Redux Toolkit) 를 즐겨 사용하는데, 이런 운행은 분리되는 것이 문제이다. 왜냐하면 우리는 상점의 실례가 하나도 없기 때문이다.예, 한 곳에서 저장소(백엔드 스크립트)를 초기화한 다음 변경이 발생할 때 모든 실행 시 이벤트를 보낼 수 있습니다. 그러나 이것은 저장소가 변경될 때마다 완전히 렌더링됩니다. 이것은 항상 새로운 상태 대상이기 때문입니다.그 외에 우리는 단지 한 곳에서 행동을 파견할 수 있을 뿐이다.
    그래서 나는 더러운 수작을 부리기로 결정했다.논리는 다음과 같습니다.
  • 백그라운드 스크립트
  • 에서 스토리지 초기화
  • 사용자가 팝업 창을 열면 현재 상태를 가져오고 자신의 저장소로 설정하기 위해 백그라운드에 이벤트를 보냅니다.
  • 팝업 페이지 대신 할당 기능을 사용합니다.사용자가 컨텐트를 할당하면 로컬 저장소에 대한 작업 없이 백그라운드 스크립트에 이벤트만 보내고, 백그라운드 스크립트는 이벤트를 할당하여 팝업 창으로 보내며, 팝업 창에서만 작업을 적용할 수 있습니다.
    그것은 여러 개의 실행 중인 저장소 사이에 주종 관계를 만들었다.
  • 또한 상태가 변경될 때마다 백그라운드 스크립트가 Dropbox에 업로드됩니다.

    다음은 설명된 논리 코드입니다.
    const populateBackgroundActionsMiddleware = () => (next) => (action) => {
      CommunicationService.dispatch(action);
      next(action);
    };
    
    export const getStore = (isBackground) => {
      const middleware = compact([
        isBackground && populateBackgroundActionsMiddleware
      ]);
    
      const store = configureStore({
        reducer: slice.reducer,
        middleware,
      });
    
      if (isBackground) {
        CommunicationService.onGetState((respond) => {
          respond(store.getState());
        });
        return store;
      }
    
      const originalDispatch = store.dispatch;
      store.dispatch = (action) => {
        CommunicationService.safeDispatch(action);
      };
      CommunicationService.onDispatch((action) => {
        originalDispatch(action);
      });
      CommunicationService.getState((newState) =>
        originalDispatch(slice.actions.setState(newState))
      );
      return store;
    }
    
    이제 Redux를 단일 런타임처럼 사용할 수 있습니다.🎉 🎉 🎉

    데이터 손실 보호


    앞에서 말한 바와 같이 매번 변경할 때마다 백엔드 스크립트는 상태를 Dropbox에 업로드하는데 사용자가 두 대의 컴퓨터를 동시에 사용하면 데이터가 분실될 가능성이 높다.처음 실행할 때만 Dropbox에서 상태를 다운로드한 다음 상태가 변할 때만 Dropbox에 업로드하기 때문이다.이 문제를 해결하기 위해서, 우리는 모든 사용자 세션에 유일한 id를 생성합니다.그리고 사용자가 상태를 Dropbox에 올릴 때, 우리는'session.json'이라는 작은 파일과 세션 id를 올립니다. 매번 상태가 올릴 때마다 이 세션 파일을 다운로드하고, id를 현재 파일과 비교합니다. 만약 그렇지 않으면 Dropbox에서 상태를 다운로드하고 현재 상태와 합쳐서 올립니다.전체 프로세스는 확장 속도를 느리게 하기 때문에 (검색할 때가 아니라 이미지와 탭을 추가할 때) 기본적으로 확장을 사용하지 않습니다. 사용자는 설정 페이지에서 사용해야 합니다.
    다음은 순서도입니다.

    결론


    찬성 의견:
  • 무료와 재미
  • 사용자의 데이터를 완전히 사유화시켰다. 왜냐하면 그들은 자신의 Dropbox
  • 를 직접 사용하기 때문이다.
    속임수:
  • 데이터를 자주 변경할 때 대역폭 사용
  • DB가 크면 애플리케이션이 느려집니다
  • .
    이것은 내가 유사 이래의 첫 번째 문장으로, 다른 사람을 도울 수 있기를 희망하며, 만약 어떤 피드백이 있다면, 나는 감격을 금할 수 없을 것이다.건배

    좋은 웹페이지 즐겨찾기