WordPress:让站内资源使用相对路径

相对路径

好处:

  1. 引用站内资源,可以使加载速度更快一些;
  2. 更好的支持SSL(浏览器不会警告不安全信息);
  3. 别人复制数据直接粘贴,无法显示

Linux+Nginx+PHP+MySQL

插件和改代码

// 修改主题的functions.php 里面的clear_urlcan函数为下面.
// 建议先备份一下之前的.
function clear_urlcan($url){
    $rstr='';
    $tmparr=parse_url($url);
    //$rstr=empty($tmparr['scheme'])?'https://':$tmparr['scheme'].'://';
    //$rstr.=$tmparr['host'].$tmparr['path'];
    $rstr=$tmparr['path'];
    return $rstr;
}

然后安装插件:Root Relative URLs
安装之后,然后修改该插件的sb_root_relative_urls.php文件中的函数为下面这个:

static function scheme( $url ) {
        //And this here is a prime example of why absolute urls in WordPress create extra overhead and processing.
        //And in the core, they use four different approaches to acheive this translation!
        //For reference, see: http://core.trac.wordpress.org/ticket/19037
        //if (is_ssl()) {
            $url = str_replace('http://', 'https://', $url);
        //}
        //else {
          //  $url = str_replace('https://', 'http://', $url);
        // }
        return $url;
    }

然后就可以了..
如果不修改第一个,只安装并启用了插件,会有资源访问不上.

搞定.

Go:解析JSON

开始

按照《Go语言编程》第五章的例子来的…(有很大改动,不然运行不了)
这本书是2012年左右出的,那时候Golang还没出1.0版本.
而现在Golang已经1.8版本了,改了不少东西才能正常的跑起来……
大概2017-03-11 0:30 开始写的…
这会3:15
……

搞完静态文件(就一个妹子UI的CSS),
已经3.40了…

还查了不少golang的文档,这下算是入坑了..

这是昨天改的一个梨子,也先贴一下吧.

Go相册网站程序

还有个问题,就是上传的图片名称会多一段数字,暂时没处理,但是不影响查看。
使用Go版本1.8

Go相册程序目录结构
uploads目录下面的文件是上传的,上传之后就可以看到了


package main

// 文件:photoweb.go
import (
	"io"
	"os"
	"log"
	"path"
	"net/http"
	"fmt"
	"io/ioutil"
	"html/template"
	"runtime/debug"
	"path/filepath"
)

/*
		 -----------------**********--------------------------------


		 运行方式: Golang 1.8 ,sublime text3 (安装之后要设置一个Go项目文件夹[go.exe只会从这个目录下面找可执行文件],具体百度)
		 
		 文件放在:E:\TMP\go\
		 目录下面,项目名字叫photoweb

		 然后直接启动就行,接着打开浏览器访问:
		 	http://localhost:8080/


		 搞定.
		 按照《Go语言编程》第五章的例子来的...(有很大改动,不然运行不了)
		 这本书是2012年左右出的,那时候Golang还没出1.0版本.
		 而现在Golang已经1.8版本了,改了不少东西才能正常的跑起来......
		 大概2017-03-11 0:30 开始写的...
		 这会3:15
		 ......

		 搞完静态文件(就一个妹子UI的CSS),
		 已经3.40了...

		 还查了不少golang的文档,这下算是入坑了..

		 by prd.


*/

const(
	ListDir = 0x0001
	UPLOAD_DIR="E:\\TMP\\go\\photoweb\\uploads\\"
	TEMPLATE_DIR = "./views"
)


var templates = make(map[string]*template.Template)
var tmpl = "tmpl"

/*

用不了,换了

// 静态文件读取
func staticDirHandler(mux *http.ServeMux,prefix string,
	staticDir string,flags int) {
	mux.HandleFunc(prefix,func(w http.ResponseWriter,r *http.Request){
		fileinfo := staticDir + r.URL.Path[len(prefix)-1:]
		fmt.Println(fileinfo)
		if (flags & ListDir) == 0 {
			if exists := isExists(fileinfo); !exists{
				http.NotFound(w,r)
				return
			}
		}
			http.ServeFile(w,r,fileinfo)
		})
}*/

// 错误处理
func check(err error) {
	if err != nil {
		panic(err)
	}
}


/* 上传图片. */
func uploadHandler(w http.ResponseWriter,r *http.Request) {
	if r.Method == "GET"{
		renderHtml(w,"upload.html",nil)
		//t.Execute(w,nil)
	}
	if r.Method == "POST"{
		f,h,err := r.FormFile("image")
		if err != nil {
			check(err)
			return
		}
		var filenamesinfo = h.Filename
		defer f.Close()
		fmt.Println(filenamesinfo)
		t,err := ioutil.TempFile(UPLOAD_DIR,filenamesinfo)
		check(err)
		defer t.Close()
		io.Copy(t,f)
		check(err)
		fainfo := filepath.Base(t.Name())
		fmt.Println("____________________")
		fmt.Println(fainfo)
		fmt.Println("____________________")
		http.Redirect(w,r,"view?id="+fainfo,http.StatusFound)
		}
}

/* 显示图片. */
func viewHandler(w http.ResponseWriter,r *http.Request) {
	imageId := r.FormValue("id")
	imagePath := UPLOAD_DIR + "\\" + imageId
	if exists := isExists(imagePath);!exists{
		http.NotFound(w,r)
		return
	}
	w.Header().Set("Content-Type","image")
	http.ServeFile(w,r,imagePath)
}

// 检查文件是否存在.
func isExists(path string) bool {
	_,err := os.Stat(path)
	if err == nil {
		return true
	}
	return os.IsExist(err)
}


// 列出所有图片.
func listHandler(w http.ResponseWriter,r *http.Request) {
	fileInfoArr,err := ioutil.ReadDir("E:\\TMP\\go\\photoweb\\uploads\\")
	check(err)
	//var listHtml string
	locals := make(map[string]interface{})
	images := []string{}
	for _,fileInfo := range fileInfoArr{
		//fmt.Println(fileInfo)
		images = append(images,fileInfo.Name())
	}
	locals["images"] = images
	renderHtml(w,"list.html",locals)
}


// 模板渲染方法.
func renderHtml(w http.ResponseWriter,tmpl string,locals map[string]interface{}){
	err := templates[tmpl].Execute(w,locals)
	check(err)
}

// 初始化方法,在main之前运行.
func init() {
	fileInfoArr,err := ioutil.ReadDir(TEMPLATE_DIR)
	fmt.Println(err)
	//panic(err)
	var templateName,templatePath string
	for _,fileInfo := range fileInfoArr{
		fmt.Println("_____")
		fmt.Println(fileInfo.Name())
		templateName = fileInfo.Name() //fileInfo.Name
		if ext := path.Ext(templateName); ext !=".html"{
			continue
		}
		templatePath = TEMPLATE_DIR + "\\" + templateName
		log.Println("Loading template:", templatePath)
		var t =  template.Must(template.ParseFiles(templatePath))
		templates[fileInfo.Name()] = t
	}
}

// 闭包.
func safeHandler(fn http.HandlerFunc)http.HandlerFunc {
	return func (w http.ResponseWriter,r *http.Request) {
		defer func(){
			if err,ok := recover().(error); ok {
				http.Error(w,err.Error(),http.StatusInternalServerError)
				// 或者输出自定义的50X错误页面
				// w.WriteHeader(http.StatusInternalServerError)
				// renderHtml(w,"error",e)
				// logging
				log.Println("WARN: panic in %v - %v ",fn,err)
				log.Println(string(debug.Stack()))
			}


		}()
		fn(w,r)
	}
}

func main() {
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	http.HandleFunc("/",safeHandler(listHandler))
	http.HandleFunc("/upload",safeHandler(uploadHandler))
	http.HandleFunc("/view",safeHandler(viewHandler))
	// 端口.
	err := http.ListenAndServe(":8080",nil)
	if err != nil {
		log.Fatal("ListenAndServe: ",err.Error())
	}
}

列表页:list.html

<!doctype html>
<html>
<head>
	<meta charset="utf-8" />
	<title>列表</title>
	<link rel="stylesheet" type="text/css" href="/static/amazeui.min.css" /> 
</head>	
<body>
	<ol>
		{{ range $.images }}
		<li><a href="/view?id={{.|urlquery}}" target="_blank">{{.|html}}</a></li>
		{{end}}
	</ol>
		<pre>
		 搞定.
		 按照《Go语言编程》第五章的例子来的...(有很大改动,不然运行不了)
		 这本书是2012年左右出的,那时候Golang还没出1.0版本.
		 而现在Golang已经1.8版本了,改了不少东西才能正常的跑起来......
		 大概2017-03-11 0:30 开始写的...
		 这会3:15
		 ......
		 搞完静态文件(就一个妹子UI的CSS),
		 已经3.40了...


		 还查了不少golang的文档,这下算是入坑了..

		 by prd.
		</pre>
	 
	 <a href="/upload">上传</a>
</body>
</html>

上传页面:upload.html

<!doctype html>
<html>
<head>
	<meta charset="utf-8" />
	<title>上传</title>
</head>	
<body>
	<form method="POST" action="/upload"  enctype="multipart/form-data"> 
			  Choose an image to upload: <input name="image" type="file" />
			 <input type="submit" value="Upload" /> 
			</form>
			<a href="/">首页</a>
</body>
</html>

还有一个文件是妹子UI的css,可以在网上直接保存一份(ctrl+s),只是保存到指定目录就可以.[参考地址]

Go语言Logo

解析JSON数据

JSON解析成Go结构体,可以使用这个工具,直接获取相关结构体

源码如下(优先从网络获取数据,若从网络获取、解析失败,则直接使用本地数据[网络获取的数据与本地数据一样]):

package main

import (
	"fmt"
	"net/http"
	"encoding/json"
	"io/ioutil"
)


/**

参考(json to go):
https://mholt.github.io/json-to-go/


golang 解析json字符串.


date:2017-03-11
by:prd.

 */


type JsonInfoObj struct {
	Sites []struct {
		Name    string `json:"Name"`
		URL     string `json:"Url"`
		Country string `json:"Country"`
	} `json:"sites"`
}


/*

获取json数据-本地数据.

*/
func getJson() ([]byte) {
	return []byte(`{"sites":[{"Name":"菜鸟教程","Url":"www.runoob.com","Country":"CN"},{"Name":"Google","Url":"www.google.com","Country":"USA"},{"Name":"Facebook","Url":"www.facebook.com","Country":"USA"},{"Name":"微博","Url":"www.weibo.com","Country":"CN"}]}`)
}

/*

 从网络上获取Json数据.
 此函数获取的结果与getJson()中的内容一致.

 */
func getNetWorkJson() ([]byte) {
	fmt.Println("-----------从网络获取Json数据开始------------")
	resp, err := http.Get("http://www.runoob.com/try/angularjs/data/sites.php")
	if err != nil {
		// panic(err.Error())
		fmt.Println("-----------从网络获取失败,直接返回本地数据------------")
		return getJson()
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// panic(err.Error())
		fmt.Println("-----------解析网络数据失败,直接返回本地数据------------")
		return getJson()
	}
	fmt.Println("-----------从网络获取Json数据成功------------")
	return body
}

/*

   显示JSON.

 */
func showJson() {
	jsoninfo := getNetWorkJson()
	var siteinfoJson JsonInfoObj
	err := json.Unmarshal(jsoninfo, &siteinfoJson)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("%+v", siteinfoJson)
}

func main() {
	showJson()
}

Linux:配置SSL遇到的问题

问题是这样的

环境:Centos,Flask,Let’s Encrypt.

使用下面的方式,来安装SSL,发现在Wordpress程序上没有任何问题,而在安装Flask程序时,则出现了问题。具体往下看。

在Flask程序上申请SSL证书,出现下面的提示:

Failed authorization procedure.
The following errors were reported by the server

内容来自:https://www.freehao123.com/lets-encrypt/

问题已经解决了,用的是Certbot,我把我的方法贴一下:
首先要说明一下几点:
1.存在一个已经建立的虚拟主机
2.我用的是oneinstack
3.Python的版本是2.7以下(如果是2.7以上SSL证书会自动安装,不用手动的)
4.使用Certbot脚本
————-分界线————————————–
过程:
1.去Certbot的官网找到与web环境相应的脚本(官网qi姐已经贴出来了)
2.按照官网的步骤来:(这是CentOS6 ,Nginx的脚本,不要直接复制哦,要按照自己的情况来)
# wget https://dl.eff.org/certbot-auto
# chmod a+x certbot-auto
$ ./certbot-auto
——————-分界线———————–
然后Python版本低于2.7的服务器就会出现问题了
Certbot会报错,代码如下:
Installing Python packages…
Installation succeeded.
/root/.local/share/letsencrypt/lib/python2.6/site-packages/cryptography/__init__.py:26: DeprecationWarning: Python 2.6 is no longer supported by the Python core team, please upgrade your Python. A future version of cryptography will drop support for Python 2.6
DeprecationWarning
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Failed to find apachectl in PATH: /usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/mysql/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
/root/.local/share/letsencrypt/lib/python2.6/site-packages/certbot/main.py:568: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
return e.message
Certbot doesn’t know how to automatically configure the web server on this system. However, it can still get a certificate for you. Please run “certbot-auto certonly” to do so. You’ll need to manually configure your web server to use the resulting certificate.
——————-分界线————————–
我们不用管它,因为他说了,你可以手动安装SSL,那我们就手动安装
——————-分界线——————————
输入命令:
# ./certbot-auto certonly
然后它依旧会报错,那我们依旧不管他
继续进行命令,因为我们是手动配置
——————–分界线——————————–
再输入上面的命令以后,会出现选项,一个是独立服务器,一个是web服务
我们选择1,web服务
它会要求我们输入email(可以不输入),那我们输入email
———————–分界线—————————–
接下来它会要求我们输入域名
输入域名
————————分界线—————————
然后它会要求我们给出域名所在的根目录
用的oneinstack的话就输入
/data/wwwroot/你的域名
————————-分界线———————–
返回如下代码,获得SSL 证书:
IMPORTANT NOTES:
– Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/ex.acgbuster.com/fullchain.pem. Your cert
will expire on 2017-05-02. To obtain a new or tweaked version of
this certificate in the future, simply run certbot-auto again. To
non-interactively renew *all* of your certificates, run
“certbot-auto renew”
– If you like Certbot, please consider supporting our work by: 
 
Donating to ISRG / Let’s Encrypt: https://letsencrypt.org/donate
Donating to EFF:
————————–分界线——————————-

众所周知,Flask的目录结构是:

Flask项目目录结构

在使用

./certbot-auto certonly

命令之后,如果输入的是/flaskxxx这个目录,那么就会生成红色框内的目录(Let’s Encrypt会在网站根目录生成一个目录里面会放一个验证程序[类似于验证文件],随后程序会进行访问相关地址进行匹配),用过Flask的都知道,这个红色的目录肯定是不对的(Flask一般读取templates目录下面的文件)。

所以,在Flask上申请SSL的时候,就遇到了这个问题。

我们只能从侧面去解决这个问题。

Linux+Nginx+PHP+MySQL

解决方案

在你的Flask文件中加入下面的代码,然后再次执行

./certbot-auto certonly

就可以实现验证,也就可以申请到SSL证书了。

2017.5.15更新:当文件不存在时,不显示详细路径(加入try/except处理).

from flask import make_response
import os

@app.route('/.well-known/acme-challenge/<checkinfo>')
def checkSSL(checkinfo):
    base_dir = os.path.dirname(__file__)
    checkinfo = 'templates/.well-known/acme-challenge/'+checkinfo
    try:
        resp = make_response(open(os.path.join(base_dir,checkinfo)).read())
        return resp
    except IOError as err:
        return 'File Error'
    return 'hi'

修改Python文件之后,如果使用的是uwsgi+nginx架构,只需要重启uwsgi即可.

ps -ef | grep uwsgi
root      9977     1  0 19:41 ?        00:00:00 uwsgi -x xxx.xml -d uwsgi.log --pidfile /tmp/uwsgi.pid
kill -9 9977
# 9977 是程序的进程号.
# 在下面再次运行uwsgi即可.

折腾一下午这个问题……

另外,下午将目前的几个站全都升级了SSL。只是遗憾的是,国内的淘宝联盟不支持SSL,代码只能显示空白了。(百度统计,CNZZ都支持SSL,而51LA目前还不支持SSL),还好GG支持SSL,直接就可以用了。