By yugasun from yugasun.com/post/server… This article can be reproduced in full, but the original author and source need to be retained.

background

As a programmer, we will be exposed to all kinds of English documents and codes in our daily work and study, so basic English is indispensable. But the English vocabulary in our mind is limited, there will always be some unknown words, so a good translation software is particularly important. Because every time we click on the translation software, and then input strange words to get answers, we always feel too cumbersome, and most of the time we only need a simple translation on the line, not a lot of translation explanations listed by the translation software. Hence the idea of a simple translation tool.

thinking

To develop a translation tools, the first reaction is to think of using off-the-shelf translation interface, only need I write a few lines local calls, can process the data line, at the same time I also want to make a simple service, it can through the way of a simple query API, you can get translation, ok, now the demand is very clear:

A free translation interface 1. I need a simple translation service which is rarely used 2. 3. I'm a poor B, and I don't want to spend moneyCopy the code

Write down the third, I silently wipe away the tears of the canthus, may be old, easy to enter the sand……

To prepare

I don’t know why, the first thing that comes to my mind is cloud function, because it meets all the requirements mentioned above, the key is she free, free, free……. The important thing is to say it three times. There are limits to free, of course, and for this gadget, that’s enough. To be a qualified fleecer, the ability to find free service and insight is a basic skill.

So three five except two registered a Tencent cloud account, homeodynamics opened cloud function services.

Next is the translation interface, in Tencent cloud platform search, just Tencent cloud machine translation of text translation interface can meet the demand, the focus is that it has 5 million characters a month free amount, is simply such a diaosi Gospel……

Another very important step is to create the API key, because the API key is required for both cloud API request and SCF command-line tool deployment. You only need to create the API key in the Cloud console.

Authentication development

The next step is formal development. Tencent cloud machine Translation interface authentication has two signature algorithms: one is simple HMAC-SHA1/SHA256 algorithm, the other is relatively complex TC3-HMAC-SHA256 algorithm. The official explanation:

Compared with the previous HmacSHA1 and HmacSHA256 signature methods, tc3-HMAC-SHA256 signature method overcovers the previous signature methods, is more secure, supports larger requests, supports JSON format, and has improved performance. Therefore, it is recommended to use this signature method to calculate signatures.

Considering the future expansibility (as a programmer like to install X), resolutely chose the second authentication algorithm. However, the official documentation does not provide an implementation version of Javascript, so I spent my time writing the signature algorithm in Typescript. It is not difficult as a whole. I just need to implement it step by step according to the official documentation.

The core code is as follows:

// 1. create Canonical request string
const HTTPRequestMethod = (options.method || "POST").toUpperCase();
const CanonicalURI = "/";
const CanonicalQueryString = "";
const CanonicalHeaders = `content-type:application/json\nhost:${Host}\n`;
const SignedHeaders = "content-type; host";
const HashedRequestPayload = crypto
  .createHash("sha256")
  .update(JSON.stringify(payload))
  .digest("hex");
const CanonicalRequest = `${HTTPRequestMethod}\n${CanonicalURI}\n${CanonicalQueryString}\n${CanonicalHeaders}\n${SignedHeaders}\n${HashedRequestPayload}`;

// 2. create string to sign
const CredentialScope = `${date}/${options.ServiceType}/tc3_request`;
const HashedCanonicalRequest = crypto
  .createHash("sha256")
  .update(CanonicalRequest)
  .digest("hex");
const StringToSign = `${Algorithm}\n${Timestamp}\n${CredentialScope}\n${HashedCanonicalRequest}`;

// 3. calculate signature
const SecretDate = sign(date, Buffer.from(`TC3${options.SecretKey}`."utf8"));
const SecretService = sign(options.ServiceType, SecretDate);
const SecretSigning = sign("tc3_request", SecretService);
const Signature = crypto
  .createHmac("sha256", SecretSigning)
  .update(Buffer.from(StringToSign, "utf8"))
  .digest("hex");

// 4. create authorization
const Authorization = `${Algorithm} Credential=${options.SecretId}/${CredentialScope}, SignedHeaders=${SignedHeaders}, Signature=${Signature}`;
Copy the code

Here is the source code.

With the most complex signature algorithm out of the way, it’s time to develop cloud functions.

Cloud function creation

Create a cloud function, refer to the official documentation to use the console to create the function, template select Nodejs8.9 runtime environment, create a successful, online edit the function code. Of course, you can also create it locally, refer to this code template github.com/yugasun/ten… “, then modify the template.yaml file to suit your needs.

If you are a locally developed function that needs to be deployed online, you will need to use the SCF command-line tool and install it with documentation. (Of course, the deployment of cloud functions, there are many other, for you to explore)

The business development

Next is to write the business logic, the original code should contain authentication and standard cloud API request code, but considering that the future may be used again, so Tencent cloud related API request code encapsulation into TSS-CAPI module. Then the refactored function code becomes much cleaner:

const Dotenv = require("dotenv");
const { Capi } = require("tss-capi");
const path = require("path");

function scfReturn(err, data) {
  return {
    isBase64Encoded: false.statusCode: 200.headers: { "Content-Type": "application/json" },
    body: { error: err, data: data }
  };
}

exports.main_handler = async (event, context, callback) => {
  const query = event.queryString || {};
  const sourceText = query.q;
  if(! sourceText) {return scfReturn(new Error("Please set word you want to translate."), null);
  }
  try {
    const envPath = path.join(__dirname, ".env");
    const { parsed } = Dotenv.config({
      path: envPath
    });

    const client = new Capi({
      Region: "ap-guangzhou".SecretId: parsed.TENCENT_SECRET_ID,
      SecretKey: parsed.TENCENT_SECRET_KEY,
      ServiceType: "tmt".host: "tmt.tencentcloudapi.com"
    });

    const res = await client.request(
      {
        Action: "TextTranslate".Version: "2018-03-21".SourceText: sourceText,
        Source: "auto".Target: "zh".ProjectId: 0
      },
      {
        host: "tmt.tencentcloudapi.com"});const translateText = res.Response && res.Response.TargetText;
    return scfReturn(null, translateText);
  } catch (e) {
    return scfReturn(e, null); }};Copy the code

Note: the function uses dotenv to configure the API key mentioned above, and you need to put the.env file with TENCENT_SECRET_ID and TENCENT_SECRET_KEY in the project root directory.

The observant reader may also notice that the function returns are normalized by scfReturn. Why is this?

In normal circumstances, the result of cloud function execution can return any result, but here I click to enable the integration response when creating the API gateway trigger, but I did not pay attention to this function, so I ignored it, resulting in the interface request error, also very confused. A search reveals the official description of the integration response:

Integrated response, which means that the API gateway parses the returned content of the cloud function and constructs the HTTP response based on the parsed content. With integrated responses, you can control the status code, headers, and body content of the response autonomously through your code, and you can respond to content in non-JSON formats, such as XML, HTML, and even JS content. When the integration response is used, the data structure must be returned according to the integration response of the API gateway trigger before it can be successfully parsed by the API gateway. Otherwise, error information {“errno”:403,”error”:”Invalid SCF response format. Please check your SCF response format.”} is displayed.

Finding the cause of the interface error, we wrote the scfReturn function to normalize all interface returns.

Function deployment

With the SCF command-line tool, the deployment of cloud functions is quite simple. Just run the SCF deploy command in the root directory of your project and everything will be taken care of automatically. If you want to create API gateway triggers automatically, you need to configure them in template.yaml as follows:

Resources:
  default:
    Type: TencentCloud::Serverless::Namespace
    dict:
      Type: TencentCloud::Serverless::Function
      Properties:
        CodeUri: . /
        Description: Tencent Machine Translator
        Environment:
          Variables: {}
        Handler: index.main_handler
        Role: QCS_SCFExcuteRole
        MemorySize: 128
        Runtime: Nodejs8.9
        Timeout: 3
        VpcConfig:
          SubnetId: ""
          VpcId: ""
        Events:
          dict:
            Type: APIGW
            Properties:
              StageName: release
              ServiceId: service-7kqwzu92
              HttpMethod: ANY
Copy the code

Note: Service-7kqwzu92 in the configuration is the service I created in the API gateway and needs to be changed to a private configuration. QCS_SCFExcuteRole is a function running Role configured. If it is not needed, you can delete Role: QCS_SCFExcuteRole.

If you run SCF deploy again after The first successful deployment, a message is displayed indicating that default dict: The function already exists. If the deploy-f function already exists, you need to override it by changing the deployment command to SCF deploy-f.

The last

Finally a simple free cloud dictionary development well, the browser to access: service-7kqwzu92-1251556596.gz.apigw.tencentcs.com/test/dictt?… , successfully output the translation result:

{
  "isBase64Encoded": false."statusCode": 200."headers": {
    "Content-Type": "application/json"
  },
  "body": {
    "error": null."data": "Hello"}}Copy the code

Of course, this is not enough for me as a lazy programmer, because NOW I need to open the browser and type the string I want to translate, so I wrote a simple script locally, by executing the terminal command, the final result is:

$ dict billionaireThe billionaireCopy the code

For some reason, when I saw the billionaire’s translation output to the command line, a grain of sand somehow flew into my eyes:

Isn’t the biggest money only 100 yuan? There are hundreds of millions of this unit……

The source code

Friends please stay, source here: github.com/yugasun/ten…