GO의 기본 MVC 웹 응용 프로그램
이 프로젝트는 프레임 워크없이 GO 언어를 사용하여 웹 사이트를 구성하고 구축하는 방법을 보여줍니다. http://www.josephspurrier.com/go-web-app-example/에서 읽을 수있는 블로그 기사가 있습니다. https://github.com/verifiedninja/webapp에서 이전 버전의 프로젝트로 구축 한 전체 응용 프로그램이 있습니다. 이 프로젝트에는 https://github.com/josephspurrier/gowebapi에 API 버전이 있습니다.
다운로드하려면 다음 명령을 실행하십시오.
go get github.com/josephspurrier/gowebapp
Go 1.5 인 경우 GovendorExperiment를 1로 설정해야합니다. 1.4 이하로 이동하는 경우 코드는 공급 업체 폴더를 사용하므로 작동하지 않습니다.
응용 프로그램을 시작하면 gowebapp.db 파일이 생성됩니다.
루트 디렉토리에서 빌드하고 실행합니다. http : // localhost로 웹 브라우저를 엽니 다. 환영 페이지를 볼 수 있습니다.
로그인 페이지로 이동 한 다음 레지스터 페이지로 이동하십시오. 새 사용자를 만들면 로그인 할 수 있어야합니다. 그게 다야.
MongoDB를 시작하십시오.
config/config.json을 열고 데이터베이스 섹션을 편집하여 연결 정보가 MongoDB 인스턴스와 일치합니다. 또한 볼트에서 mongoDB로 유형을 변경하십시오.
루트 디렉토리에서 빌드하고 실행합니다. http : // localhost로 웹 브라우저를 엽니 다. 환영 페이지를 볼 수 있습니다.
로그인 페이지로 이동 한 다음 레지스터 페이지로 이동하십시오. 새 사용자를 만들면 로그인 할 수 있어야합니다. 그게 다야.
MySQL을 시작하고 config/mysql.sql을 가져 와서 데이터베이스 및 테이블을 만듭니다.
config/config.json을 열고 데이터베이스 섹션을 편집하여 연결 정보가 MySQL 인스턴스와 일치합니다. 또한 Bolt에서 MySQL로 유형을 변경하십시오.
루트 디렉토리에서 빌드하고 실행합니다. http : // localhost로 웹 브라우저를 엽니 다. 환영 페이지를 볼 수 있습니다.
로그인 페이지로 이동 한 다음 레지스터 페이지로 이동하십시오. 새 사용자를 만들면 로그인 할 수 있어야합니다. 그게 다야.
웹 앱에는 공개 홈페이지, 인증 된 홈페이지, 로그인 페이지, 등록 페이지, 페이지 정보 및 CRUD 작업을 보여주는 간단한 메모장이 있습니다.
웹 앱의 Entrypoint는 Gowebapp.go입니다. 파일은 응용 프로그램 설정을로드하고, 세션을 시작하고, 데이터베이스에 연결하고, 템플릿을 설정하고, 경로를로드하고, 미들웨어를 첨부하고, 웹 서버를 시작합니다.
프론트 엔드는 글꼴과 간격에 약간의 작은 변경 사항이있는 부트 스트랩을 사용하여 구축됩니다. 플래시 메시지는 화면 오른쪽 하단에 표시되도록 사용자 정의됩니다.
모든 오류 및 경고 메시지는 사용자 또는 콘솔에 표시되어야합니다. 정보 메시지는 4 초 후에 사라지는 플래시 메시지를 통해 사용자에게 표시됩니다. 플래시 메시지는 정적 폴더의 JavaScript에 의해 제어됩니다.
최근 폴더 구조가 변경되었습니다. 모든 포크를보고 다른 장소에서 프로젝트를 재사용 한 후, 나는 Github 경로가 많은 가져 오기 전체에 걸쳐 Github 경로가 흩어지지 않도록 공급 업체 폴더 내부의 앱 폴더로 이동 코드를 이동하기로 결정했습니다. 상대 경로를 사용하고 싶지 않아서 공급 업체 폴더가 최선의 선택처럼 보였습니다.
이 프로젝트는 다음 폴더로 구성됩니다.
config - application settings and database schema
static - location of statically served files like CSS and JS
template - HTML templates
vendor/app/controller - page logic organized by HTTP methods (GET, POST)
vendor/app/shared - packages for templates, MySQL, cryptography, sessions, and json
vendor/app/model - database queries
vendor/app/route - route information and middleware
몇 가지 외부 패키지가 있습니다.
github.com/gorilla/context - registry for global request variables
github.com/gorilla/sessions - cookie and filesystem sessions
github.com/go-sql-driver/mysql - MySQL driver
github.com/haisum/recaptcha - Google reCAPTCHA support
github.com/jmoiron/sqlx - MySQL general purpose extensions
github.com/josephspurrier/csrfbanana - CSRF protection for gorilla sessions
github.com/julienschmidt/httprouter - high performance HTTP request router
github.com/justinas/alice - middleware chaining
github.com/mattn/go-sqlite3 - SQLite driver
golang.org/x/crypto/bcrypt - password hashing algorithm
템플릿은 템플릿 폴더 아래 폴더로 구성됩니다.
about/about.tmpl - quick info about the app
index/anon.tmpl - public home page
index/auth.tmpl - home page once you login
login/login.tmpl - login page
notepad/create.tmpl - create note
notepad/read.tmpl - read a note
notepad/update.tmpl - update a note
partial/footer.tmpl - footer
partial/menu.tmpl - menu at the top of all the pages
register/register.tmpl - register page
base.tmpl - base template for all the pages
템플릿과 정적 파일을보다 쉽게 작업 할 수있는 몇 가지 템플릿 기능이 있습니다.
<!-- CSS files with timestamps -->
{{CSS "static/css/normalize3.0.0.min.css"}}
parses to
< link rel =" stylesheet " type =" text/css " href =" /static/css/normalize3.0.0.min.css?1435528339 " />
<!-- JS files with timestamps -->
{{JS "static/js/jquery1.11.0.min.js"}}
parses to
< script type =" text/javascript " src =" /static/js/jquery1.11.0.min.js?1435528404 " > </ script >
<!-- Hyperlinks -->
{{LINK "register" "Create a new account."}}
parses to
< a href =" /register " > Create a new account. </ a >
<!-- Output an unescaped variable (not a safe idea, but I find it useful when troubleshooting) -->
{{.SomeVariable | NOESCAPE}}
<!-- Time format -->
{{.SomeTime | PRETTYTIME}}
parses to format
3:04 PM 01/02/2006템플릿에서도 사용할 수있는 몇 가지 변수가 있습니다.
<!-- Use AuthLevel=auth to determine if a user is logged in (if session.Values["id"] != nil) -->
{{if eq .AuthLevel "auth"}}
You are logged in.
{{else}}
You are not logged in.
{{end}}
<!-- Use BaseURI to print the base URL of the web app -->
< li > < a href =" {{.BaseURI}}about " > About </ a > </ li >
<!-- Use token to output the CSRF token in a form -->
< input type =" hidden " name =" token " value =" {{.token}} " >폐쇄 및 태그 전에 템플릿 별 코드를 추가하는 것도 쉽습니다.
<!-- Code is added before the closing </head> tag -->
{{define "head"}} < meta name =" robots " content =" noindex " > {{end}}
...
<!-- Code is added before the closing </body> tag -->
{{define "foot"}}{{JS "//www.google.com/recaptcha/api.js"}}{{end}}JavaScript를 사용하여 플래시 알림을 트리거 할 수 있습니다.
flashError ( "You must type in a username." ) ;
flashSuccess ( "Record created!" ) ;
flashNotice ( "There seems to be a piece missing." ) ;
flashWarning ( "Something does not seem right..." ) ; 컨트롤러 파일은 모두 동일한 패키지 이름을 공유합니다. 이렇게하면 경로를 매핑 할 때 패키지 수가 줄어 듭니다. 또한 각 기능에 대한 좋은 명명 규칙을 사용하여 각 기능의 위치와 각각의 HTTP 요청 유형을 알 수 있습니다.
고릴라 세션 액세스 :
// Get the current session
sess := session . Instance ( r )
...
// Close the session after you are finished making changes
sess . Save ( r , w )다음 페이지에서 4 가지 유형의 플래시 메시지 중 1 개 트리거 (다른 코드가 필요하지 않음) :
sess . AddFlash (view. Flash { "Sorry, no brute force :-)" , view . FlashNotice })
sess . Save ( r , w ) // Ensure you save the session after making a change to it형태 필드가 비어 있지 않은 유효성 :
// Ensure a user submitted all the required form fields
if validate , missingField := view . Validate ( r , [] string { "email" , "password" }); ! validate {
sess . AddFlash (view. Flash { "Field missing: " + missingField , view . FlashError })
sess . Save ( r , w )
LoginGET ( w , r )
return
}템플릿 렌더링 :
// Create a new view
v := view . New ( r )
// Set the template name
v . Name = "login/login"
// Assign a variable that is accessible in the form
v . Vars [ "token" ] = csrfbanana . Token ( w , r , sess )
// Refill any form fields from a POST operation
view . Repopulate ([] string { "email" }, r . Form , v . Vars )
// Render the template
v . Render ( w )AJAX 요청 중에 플래시 메시지를 반환하십시오.
// Get session
sess := session . Instance ( r )
// Set the flash message
sess . AddFlash (view. Flash { "An error occurred on the server. Please try again later." , view . FlashError })
sess . Save ( r , w )
// Display the flash messages as JSON
v := view . New ( r )
v . SendFlashes ( w )데이터베이스 쿼리 처리 :
// Get database result
result , err := model . UserByEmail ( email )
if err == sql . ErrNoRows {
// User does not exist
} else if err != nil {
// Display error message
} else if passhash . MatchString ( result . Password , password ) {
// Password matches!
} else {
// Password does not match
}이메일 보내기 :
// Email a user
err := email . SendEmail ( email . ReadConfig (). From , "This is the subject" , "This is the body!" )
if err != nil {
log . Println ( err )
sess . AddFlash (view. Flash { "An error occurred on the server. Please try again later." , view . FlashError })
sess . Save ( r , w )
return
}구성에서 Google Recaptcha가 활성화 된 경우 양식을 확인하십시오.
// Validate with Google reCAPTCHA
if ! recaptcha . Verified ( r ) {
sess . AddFlash (view. Flash { "reCAPTCHA invalid!" , view . FlashError })
sess . Save ( r , w )
RegisterGET ( w , r )
return
}데이터베이스 계층을 추상화하는 것이 좋습니다. 따라서 변경 해야하는 경우 쿼리를 찾기 위해 비즈니스 로직을 살펴볼 필요가 없습니다. 모든 쿼리는 모델 폴더에 저장됩니다.
이 프로젝트는 Boltdb, MongoDB 및 MySQL을 지원합니다. 모든 쿼리는 동일한 파일에 저장되므로 구성 파일 이외의 내용을 수정하지 않고도 데이터베이스를 쉽게 변경할 수 있습니다.
user.go 및 note.go 파일은 모델 디렉토리의 루트에 있으며 각 데이터베이스 유형에 대한 모든 쿼리를 삭제 한 것입니다. 모델에는 Structs가 지원되는 모든 데이터베이스와 함께 작동하도록하는 몇 가지 해킹이 있습니다.
데이터베이스에 연결하십시오 (응용 프로그램에서 한 번만 필요한 경우) :
// Connect to database
database . Connect ( config . Database )데이터베이스에서 읽기 :
result := User {}
err := database . DB . Get ( & result , "SELECT id, password, status_id, first_name FROM user WHERE email = ? LIMIT 1" , email )
return result , err데이터베이스에 쓰기 :
_ , err := database . DB . Exec ( "INSERT INTO user (first_name, last_name, email, password) VALUES (?,?,?,?)" , firstName , lastName , email , password )
return err 몇 가지 미들웨어가 포함되어 있습니다. CSRFBANANA라는 패키지는 크로스 사이트 요청 위조 공격으로부터 보호하고 이중 제출을 방지합니다. 패키지 httprouterWrapper는 httprouter와 funcs를 호환 할 수있는 헬퍼 기능을 제공합니다. 패키지 logrequest는 웹 사이트에 대한 모든 요청을 콘솔에 기록합니다. PPROFHANDLER 패키지는 PPROF를 활성화하므로 HTTPROUTER에서 작동합니다. Route.go에서 모든 개별 노선은 Alice를 사용하여 체인을 매우 쉽게 만듭니다.
웹 앱을 좀 더 유연하게 만들려면 config.json 파일을 통해 한 곳에서 다른 구성 요소를 변경할 수 있습니다. 자신의 설정을 추가하려면 config.json에 추가하고 Gowebapp.go 및 개별 파일에서 structs를 업데이트하여 코드에서 참조 할 수 있습니다. config.json :
{
"Database" : {
"Type" : " Bolt " ,
"Bolt" : {
"Path" : " gowebapp.db "
},
"MongoDB" : {
"URL" : " 127.0.0.1 " ,
"Database" : " gowebapp "
},
"MySQL" : {
"Username" : " root " ,
"Password" : " " ,
"Name" : " gowebapp " ,
"Hostname" : " 127.0.0.1 " ,
"Port" : 3306 ,
"Parameter" : " ?parseTime=true "
}
},
"Email" : {
"Username" : " " ,
"Password" : " " ,
"Hostname" : " " ,
"Port" : 25 ,
"From" : " "
},
"Recaptcha" : {
"Enabled" : false ,
"Secret" : " " ,
"SiteKey" : " "
},
"Server" : {
"Hostname" : " " ,
"UseHTTP" : true ,
"UseHTTPS" : false ,
"HTTPPort" : 80 ,
"HTTPSPort" : 443 ,
"CertFile" : " tls/server.crt " ,
"KeyFile" : " tls/server.key "
},
"Session" : {
"SecretKey" : " @r4B?EThaSEh_drudR7P_hub=s#s2Pah " ,
"Name" : " gosess " ,
"Options" : {
"Path" : " / " ,
"Domain" : " " ,
"MaxAge" : 28800 ,
"Secure" : false ,
"HttpOnly" : true
}
},
"Template" : {
"Root" : " base " ,
"Children" : [
" partial/menu " ,
" partial/footer "
]
},
"View" : {
"BaseURI" : " / " ,
"Extension" : " tmpl " ,
"Folder" : " template " ,
"Name" : " blank " ,
"Caching" : true
}
}https를 활성화하려면 usehttps를 true로 설정하고 루트에서 tls라는 폴더를 작성한 다음 해당 폴더에 인증서와 키 파일을 배치하십시오.
공공 가정 :
에 대한:
등록하다:
로그인:
인증 된 집 :
참고보기 :
참고 추가 :
참고 편집 :
모든 피드백을 환영합니다. 제안, 질문 또는 비판이 있으면 알려주십시오. 무언가가 관용적이지 않다면, 더 나아질 수 있도록 알려주십시오.