Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
This repository was archived by the owner on Oct 17, 2020. It is now read-only.
/shortPublic archive

URL shortening service written in Go and React

License

NotificationsYou must be signed in to change notification settings

short-d/short

Repository files navigation

Build StatuscodecovMaintainabilityGo Report CardMIT LicenseFloobits Status

Demo

Preview

Demo

Gets/ Chrome extension

Install it fromChrome Web Store or build itfromsource

Dependent Projects

  • app: Reusable framework for Go apps & commandline tools.
  • kgs: Offline unique key generation service.

Table of Contents

  1. Getting Started
    1. Accessing the source code
    2. Prerequisites
    3. Local environmental variables
    4. Create reCAPTCHA account
    5. Configure Single Sign On
    6. Backend
    7. Frontend
  2. System Design
    1. App Level Architecture
    2. Service Level Architecture
    3. Object Oriented Design
    4. Dependency Injection
    5. Database Modeling
    6. Feature Toggle
    7. Search Engine Optimization
    8. Social Media Summary Card
  3. Testing
    1. The Importance Of Automation
    2. Testing Strategy
    3. Unit Testing
    4. Integration Testing
    5. Component Testing
    6. Contract Testing
    7. End To End Testing
    8. The Test Pyramid
  4. Deployment
    1. Continuous Delivery
    2. Kubernetes
    3. GitOps
  5. Tools We Use
  6. Contributing
  7. Author
  8. License

Getting Started

Accessing the source code

git clone https://github.com/short-d/short.git

Prerequisites

Local environmental variables

  1. Copybackend/.env.dist file tobackend/.env:

    cp backend/.env.dist backend/.env
  2. Copyfrontend/.env.development.dist file tofrontend/.env.development:

    cp frontend/.env.development.dist frontend/.env.development

Create reCAPTCHA account

  1. Sign up atReCAPTCHA with thefollowing configurations:

    FieldValue
    LabelShort
    reCAPTCHA typereCAPTCHAv3
    Domainslocalhost
  2. Opensettings. CopySITE KEY andSECRET KEY.

  3. Replace the value ofRECAPTCHA_SECRET in thebackend/.env file withSECRET KEY.

  4. Replace the value ofREACT_APP_RECAPTCHA_SITE_KEY infrontend/.env.development file withSITE KEY.

Configure Single Sign On

Google

Create a new Client ID atGoogle API Credentials:

  1. Click onCreate Credentials and selectOAuth client ID.

  2. SelectWeb application forApplication type.

  3. Fill inhttp://localhost/oauth/google/sign-in/callback forAuthorized redirect URIs and click onCreate.

  4. Replace the value ofGOOGLE_CLIENT_ID inbackend/.env file withYour Client ID.

  5. Replace the value ofGOOGLE_CLIENT_SECRET inbackend/.env file withYour Client Secret.

Facebook

You can find the detailed instructions on setting up Facebook sign inhere in case you are interested in.

Github

You can find the detailed instructions on setting up Github sign inhere in case you are interested in.

Backend

  1. Update placeholder values with your own configurations.

  2. Launch backend server

    cd backend./scripts/dev
  3. Remember to install developers tools before start coding:

    ./scripts/tools

Frontend

  1. UpdateREACT_APP_RECAPTCHA_SITE_KEY infrontend/.env.development.

  2. Launch frontend server

    cd frontend./scripts/dev
  3. Visithttp://localhost:3000

System Design

App Level Architecture

Short backend is built on top ofUncle Bob's Clean Architecture, the centralobjective of which is separation of concerns.

Short Backend

It enables the developers to modify a single component of the system at a timewhile leaving the rest unchanged. This minimizes the amount of changes have tobe made in order to support new requirements as the system grows. CleanArchitecture also improves the testability of system, which in turn savesprecious time when creating automated tests.

Service Level Architecture

Short adoptsMicroservices Architecture toorganize dependent services around business capabilities and to enableindependent deployment of each service.

Short CloudSSR,Toggle,Status Page, Search,Data Reporter,Feedback Widget,and Cloud API are still under active development.

Object Oriented Design

Short leverages class design, package cohesion, and package coupling principlesto manage logical dependency between internal components.

Class Design

PrincipalDescription
Single Responsibility PrincipleA class should have one, and only one, reason to change.
Open Closed PrincipleYou should be able to extend a classes behavior, without modifying it.
Liskov Substitution PrincipleDerived classes must be substitutable for their base classes.
Interface Segregation PrincipleMake fine grained interfaces that are client specific.
Dependency Inversion PrincipleDepend on abstractions, not on concretions.

Package Cohesion

PrincipalDescription
Release Reuse Equivalency PrincipleThe granule of reuse is the granule of release.
The Common Closure PrincipleClasses that change together are packaged together.
The Common Reuse PrincipleClasses that are used together are packaged together.

Package Coupling

PrincipalDescription
Acyclic Dependencies PrincipleThe dependency graph of packages must have no cycles.
Stable Dependencies PrincipleDepend in the direction of stability.
Stable Abstractions PrincipleAbstractness increases with stability.

Dependency Injection

Short produces flexible and loosely coupled code, by explicitly providingcomponents with all of the dependencies they need.

typeAuthenticatorstruct {tokenizer          fw.CryptoTokenizertimer              fw.TimertokenValidDuration time.Duration}funcNewAuthenticator(tokenizer fw.CryptoTokenizer,timer fw.Timer,tokenValidDuration time.Duration,)Authenticator {returnAuthenticator{tokenizer:tokenizer,timer:timer,tokenValidDuration:tokenValidDuration,  }}

Short also simplifies the management of the big block of order-dependentinitialization code withWire, a compile timedependency injection framework by Google.

funcInjectGraphQlService(namestring,sqlDB*sql.DB,graphqlPath provider.GraphQlPath,secret provider.ReCaptchaSecret,jwtSecret provider.JwtSecret,bufferSize provider.KeyGenBufferSize,kgsRPCConfig provider.KgsRPCConfig,tokenValidDuration provider.TokenValidDuration,) (mdservice.Service,error) {wire.Build(wire.Bind(new(fw.GraphQlAPI),new(graphql.Short)),wire.Bind(new(url.Retriever),new(url.RetrieverPersist)),wire.Bind(new(url.Creator),new(url.CreatorPersist)),wire.Bind(new(repo.UserURLRelation),new(db.UserURLRelationSQL)),wire.Bind(new(repo.URL),new(*db.URLSql)),wire.Bind(new(keygen.KeyGenerator),new(keygen.Remote)),wire.Bind(new(service.KeyFetcher),new(kgs.RPC)),observabilitySet,authSet,mdservice.New,provider.NewGraphGophers,mdhttp.NewClient,mdrequest.NewHTTP,mdtimer.NewTimer,db.NewURLSql,db.NewUserURLRelationSQL,provider.NewRemote,url.NewRetrieverPersist,url.NewCreatorPersist,provider.NewKgsRPC,provider.NewReCaptchaService,requester.NewVerifier,graphql.NewShort,  )return mdservice.Service{},nil}

Database Modeling

Entity Relation Diagram

Feature Toggle

Short employsfeature toggles to modify system behavior without changing code.UI components controlled by the feature toggles are created inside a centralizedUIFactory in order to avoid having nestedifelse statement across thecode base:

// UIFactory.tsxexportclassUIFactory{constructor(privatefeatureDecisionService:IFeatureDecisionService){}publiccreateGoogleSignInButton():ReactElement{if(!this.featureDecisionService.includeGoogleSignButton()){return<div/>;}return(<GoogleSignInButtongoogleSignInLink={this.authService.googleSignInLink()}/>);}publiccreateGithubSignInButton():ReactElement{if(!this.featureDecisionService.includeGithubSignButton()){return<div/>;}return(<GithubSignInButtongithubSignInLink={this.authService.githubSignInLink()}/>);}}

Short also providesIFeatureDecisionService interface, allowing the developersto switch to dynamic feature toggle backend in the future by simply swappingthe dependency injected.

// FeatureDecision.service.tsexportinterfaceIFeatureDecisionService{includeGithubSignButton():boolean;includeGoogleSignButton():boolean;includeFacebookSignButton():boolean;}
// StaticConfigDecision.service.tsimport{IFeatureDecisionService}from'./FeatureDecision.service';exportclassStaticConfigDecisionServiceimplementsIFeatureDecisionService{includeGithubSignButton():boolean{returnfalse;}includeGoogleSignButton():boolean{returnfalse;}includeFacebookSignButton():boolean{returntrue;}}
// dep.tsexportfunctioninitUIFactory(  ...):UIFactory{  ...conststaticConfigDecision=newStaticConfigDecisionService();  ...returnnewUIFactory(    ...,staticConfigDecision);}

You can read about the detailed feature toggle design onthis article.

Search Engine Optimization

In order to improve the quality and quantity of the website's traffic, Shortincreases its visibility to web search engines through HTML meta tags.

<!-- ./frontend/public/index.html --><title>Short: Free online link shortening service</title><!-- Search Engine Optimization --><metaname="description"content="Short enables people to type less for their favorite web sites"><metaname="robots"content="index, follow"><linkhref="https://short-d.com"rel="canonical">

If you searchshort-d.com on Google, you should see Short shows up asthe first result:

Google Search Result

Social Media Summary Card

Facebook & LinkedIn

Short leveragesOpen Graph tags to control what content shows up inthe summary card when the website is shared on Facebook or LinkedIn:

<!-- ./frontend/public/index.html --><!-- Open Graph --><metaproperty="og:title"content="Short: Free link shortening service"/><metaproperty="og:description"content="Short enables people to type less for their favorite web sites"/><metaproperty="og:image"content="https://short-d.com/promo/small-tile.png"/><metaproperty="og:url"content="https://short-d.com"/><metaproperty="og:type"content="website"/>

Shared on Facebook:

Facebook Card

Shared on LinkedIn:

LinkedIn Card

Twitter

Twitter uses its own meta tags to determine what will show up whenthe website is mentioned in a Tweet:

<!-- Twitter --><metaname="twitter:card"content="summary_large_image"/><metaname="twitter:site"content="@byliuyang11"/><metaname="twitter:title"content="Short: Free link shortening service"/><metaname="twitter:description"content="Short enables people to type less for their favorite web sites"/><metaname="twitter:image"content="https://short-d.com/promo/twitter-card.png"/>

Twitter Card

Testing

The Importance Of Automation

Short is maintained by a small team of talented software engineers workingat Google, Uber, and Vmware as a side project. The team wants to deliver newfeatures faster without sacrificing its quality. Testing ever-increasingamount of features manually soon becomes impossible — unless we wantto spend all our time with manual, repetitive work instead of deliveringworking features.

Test automation is the only way forward.

Testing Strategy

Test Strategy

Please readTesting Strategies in a Microservice Architecturefor a detailed introduction on test strategies.

Unit Testing

A unit test exercises the smallest piece of testable software in theapplication to determine whether it behaves as expected.

Unit Test

Run unit tests for backend:

cd backend./scripts/unit-test

Sociable And Solitary

Two Types of Unit Test

The FIRST Principal

  • [F]ast: Unit tests should be fast otherwise they will slow downdevelopment & deployment.
  • [I]ndependent: Never ever write tests which depend on other test cases.
  • [R]epeatable: A repeatable test is one that produces the same resultseach time you run it.
  • [S]elf-validating: There must be no manual interpretation of the results.
  • [T]imely/[T]horoughly: Unit tests must be included for every pull requestof a new feature and cover edge cases, errors, and bad inputs.

Test Structure

An automated test method should be composed of 3As: Arrange, Act, and Assert.

  • [A]rrange: All the data needed for a test should be arranged as partof the test. The data used in a test should not depend on the environmentin which the test is running.
  • [A]ct: Invoke the actual method under test.
  • [A]ssert: A test method should test for a single logical outcome.

Integration Testing

An integration test verifies the communication paths and interactionsbetween components to detect interface defects.

Integration Test

Run integration tests for backend:

cd backend./scripts/integration-test

Component Testing

A component test limits the scope of the exercised software to a portionof the system under test, manipulating the system through internal codeinterfaces and using test doubles to isolate the code under test fromother components.

In Process

Component Test

Out Of Process

Component Test

Contract Testing

An integration contract test is a test at the boundary of an externalservice verifying that it meets the contract expected by a consumingservice.

End To End Testing

An end-to-end test verifies that a system meets external requirementsand achieves its goals, testing the entire system, from end to end.

The Test Pyramid

Test Pyramid

Deployment

Continuous Delivery

Continuous Delivery

Currently, we use continuous delivery to deploy code changes to staging &production environment.

Merging pull request into master branch on Github will automatically deploy thechanges tostaging. Merging frommaster branchtoproduction branch will automatically deploy the latest code to the production.

In the future, when after we add enough automated tests, we may migrate tocontinuous deployment instead for faster releases.

You can find the differences between continuous delivery & continuous deploymenthere

Kubernetes

Short leveragesKubernetes to automate deployment, scaling,and management of containerized microservices.

Node overview

GitOps

Short usesGitOps to configure Kubernetescluster and span up new services.

Git Ops

Tools We Use

Contributing

Please readCONTRIBUTING.md for details on our codeof conduct, the process for submitting pull requests to us, and our codereview guideline.

Author

Harry Liu -Initial work -byliuyang

As the tech lead of Short, I am responsible for the overall planning, executionand success of complex software solutions to meet users' needs.

I deeply believe in and am striving to achieve the right column of thefollowing diagram:

Manager vs Leader

License

This project is maintained under MIT license


[8]ページ先頭

©2009-2025 Movatter.jp