我正在编写一个Go应用程序来运行App Engine的Go运行时.
我注意到几乎任何使用App Engine服务的操作(例如数据存储区,邮件甚至功能)都要求您传递一个appengine.Context必须使用该函数检索其实例的操作appengine.NewContext(req *http.Request) Context.
当我为App Engine编写这个应用程序时,我希望能够轻松快速地将其移动到其他平台(可能是一个不支持任何App Engine API的应用程序).
因此,我通过围绕任何特定于App Engine的交互(包括请求处理函数)编写小包装来抽象出与App Engine服务和API的实际交互.通过这种方法,如果我希望转移到不同的平台,我将只重写那些将我的应用程序绑定到App Engine的特定模块.简单直接.
唯一的问题是那个appengine.Context对象.我不能将我的请求处理程序通过我的逻辑层传递给处理这些API的模块,而不会将我的所有代码都绑定到App Engine.我可以通过http.Request从该对象appengine.Context物体可以得出,但这需要,可能不应该再加耦合的事情.(我认为最好的做法是我的应用程序都不知道它是一个Web应用程序,除了那些专门用于处理HTTP请求的部分.)
想到的第一个解决方案是在某个模块中创建一个持久变量.像这样的东西:
package context
import (
"appengine"
)
var Context appengine.Context
Run Code Online (Sandbox Code Playgroud)
然后,在我的请求处理程序中,我可以使用context.Context = appengine.NewContext(r)和在直接使用App Engine服务的模块中设置该变量,我可以通过访问来获取上下文context.Context.没有干预代码需要知道appengine.Context对象的存在.唯一的问题是"多个请求可能由给定实例同时处理",这可能导致竞争条件和此计划的意外行为.(一个请求设置它,另一个设置它,第一个访问它并获取错误的appengine.Context对象.)
我理论上可以存储appengine.Context到数据存储区,但是我必须将一些特定于请求的标识符传递给逻辑层到特定于服务的模块,以识别appengine.Context数据存储区中哪个对象是当前请求的对象,这将再次耦合事物我认为不应该耦合.(而且,它会增加我的应用程序的数据存储使用率.)
我也可以appengine.Context使用整个类型的类型将对象传递给整个逻辑链,interface{}并且任何不需要该appengine.Context对象的模块都会忽略它.这将防止占压我的大多数应用程序的任何东西具体.然而,这似乎也非常混乱.
所以,我有点不知道如何干净地确保需要该appengine.Context对象的App-Engine特定模块可以获得它.希望你们大家能给我一个解决方案,我还没有想到自己.
提前致谢!
我在Python 3中编写了一个拦截代理,它使用中间人"攻击"技术,能够动态地检查和修改通过它的页面."安装"或设置代理的过程的一部分涉及生成要在浏览器中安装的"根"证书,并且每次通过代理通过HTTPS命中新域时,代理都会生成新的站点证书. -the-fly(并将所有生成的证书缓存到磁盘,因此它不必为已生成证书的域重新生成证书)由根证书签名并使用站点证书与浏览器进行通信.(当然,代理会伪造自己的HTTPS连接到远程服务器.如果您感到好奇,代理也会检查服务器证书的有效性.)
嗯,它适用于浏览器冲浪.(并且,这可能是相关的 - 至少在几个版本中,冲浪没有检查/强制执行证书有效性.我无法证明更新版本是否就是这种情况.)但是,Firefox给出了通过代理和Chromium发出的第二个(以及所有更晚的)HTTPS请求的SEC_ERROR_REUSED_ISSUER_AND_SERIAL错误(我没有使用适当的Chrome测试)在每个HTTPS请求上都给出了NET :: ERR_CERT_COMMON_NAME_INVALID.当尝试浏览我的拦截代理时,这些显然是一个主要问题.
我正在使用的SSL库是pyOpenSSL 0.14,如果这有任何区别的话.
关于Firefox的SEC_ERROR_REUSED_ISSUER_AND_SERIAL错误,我很确定我不会重复使用序列号.(如果有人想检查我的工作,那将是非常的rad:cert.py - 请注意第168行的"crt.set_serial_number(getrandbits(20*8))".根证书颁发者当然不会改变,但这不会改变,对吧?如果不是根证书颁发者,我不确定错误消息中"issuer"究竟是什么意思.
此外,Firefox的"查看证书"对话框显示代理生成的不同证书的完全不同的序列号.(例如,我为www.google.com生成了序列号为00的一个:BF:7D:34:35:15:83:3A:6E:9B:59:49:A8:CC: 88:01:BA:BE:23:A7:AD和另一个为www.reddit.com生成的序列号为78:51:04:48:4B:BC:E3:96:47:AC:DA:D4 :50:EF:2B:21:88:99:AC:8C.)所以,我不确定Firefox究竟在抱怨什么.
我的代理为其即时创建的所有证书重用私钥(以及公钥/模数).我开始怀疑这是Firefox正在讨论的内容,并尝试更改代码,为代理在运行中创建的每个证书生成一个新的密钥对.这并没有解决Firefox中的问题.我仍然得到相同的错误消息.我还没有测试它是否解决了Chromium问题.
关于Chromium的NET :: ERR_CERT_COMMON_NAME_INVALID错误,站点证书的通用名称应该是域名,对吧?我不应该包括端口号或任何东西,对吗?(同样,如果有人想检查我的工作,请参阅cert.py.)如果它有帮助,我的拦截代理不会在证书通用名称或任何内容中使用任何通配符.生成的每个证书都是针对一个特定的fqdn.
我非常肯定能够在不使用Firefox或Chrome(或Chromium或IE等)的情况下完成这项工作.我曾经工作过的公司购买并建立了一个中间人代理服务器,通过该代理服务器,公司网络内部的所有流量都必须通过.该公司的PC管理员在员工使用的每台公司拥有的计算机上的每个浏览器中都安装了一个自签名证书作为证书颁发机构,结果从未产生任何错误,例如Firefox和Chromium给我的证书我的自己的拦截代理软件产生.PC管理员可能会在Firefox中调整一些关于:配置设置以使这一切都能正常工作,但我对此表示怀疑.
公平地说,这家公司使用的代理是网络或传输层,而不是我的应用层.但我希望在应用层HTTP(s)代理中可以实现相同的功能.
编辑:我已经尝试按照brain99的建议设置subjectAltName.以下是我在位置brain99中添加的行建议:
r.add_extensions([crypto.X509Extension(b"subjectAltName", False, b"DNS:" + cn.encode("UTF-8"))])
我仍然从Firefox获得SEC_ERROR_REUSED_ISSUER_AND_SERIAL(在第二次和随后的HTTPS请求中,我从Chromium获得ERR_SSL_SERVER_CERT_BAD_FORMAT.
以下是代理生成的几个证书:
google.com:https://pastebin.com/YNr4zfZu
stackoverflow.com:https://pastebin.com/veT8sXZ4
编写输出有效go代码的应用程序可能最好使用内置的"go"包及其一些子包("go/ast","go/token","go/printer"等).
要创建字符串文字表达式,您需要创建ast.BasicLit:
l := &ast.BasicLit{Kind: token.STRING, Value: "\"Hello world!\""}
Run Code Online (Sandbox Code Playgroud)
在我的go程序中,我有一个字符串,我需要创建一个ast.BasicLit,当输出时会生成一个忠实再现相同字符串的字符串文字.为了做到这一点,我必须从字符串派生一个字符串,该字符串代表表示字符串的go-syntax文字.(这个概念是如此元,很难描述而没有歧义.)
我正在寻找的东西基本上相当于Python内置的repr().这是一个你可以称之为JavaScript中eval()的"反面"的操作.
一个例子应该有助于说明我在寻找什么.
package main
import (
"repr"
)
// Assume the operation I'm hoping to find is implemented in the package "repr" as a function called "StrLit()" with the signature "func(v string) string".
func main() {
println(repr.StrLit("Hello World!"))
println("a")
println(repr.StrLit("a"))
println(repr.StrLit(repr.StrLit("a")))
println(repr.StrLit("This is a\ntest!"))
println(repr.StrLit("As is\x00this!"))
}
Run Code Online (Sandbox Code Playgroud)
调用此程序时应输出以下内容:
"Hello World!"
a
"a"
"\"a\""
"This is a\ntest!"
"As is\x00this!"
Run Code Online (Sandbox Code Playgroud)
虽然我的具体问题涉及字符串,但我会对一般解决方案感兴趣,该解决方案可以处理任何类型的值(整数类型,浮点类型,甚至复杂类型),如下所示:
package main
import (
"repr"
)
// Assume this time that …Run Code Online (Sandbox Code Playgroud) 我正在创建一个多子项目Java项目.子项目每个都有自己独立的git存储库,并使用git子模块包含在超级项目中.我们首选的情况是,我们的持续集成工具(Jenkins)将独立地将这些子项目构建到.jars中,而不考虑或以其他方式了解超级项目.
这可以通过确保每个子项目都有一个build.gradle非常容易地完成,该build.gradle具有构建由构建产生的.jar所需的所有信息.结果的唯一复杂因素是某些子项目依赖于其他子项目.
如果您愿意总是让子项目从Maven或Ivy仓库中提取其依赖项'.jars,那么即使这样也非常简单.但是,当我们在开发过程中构建我们的本地盒子时,我们希望能够构建和部署超级项目的.war文件到Tomcat以及所有.jars到类路径上的某个地方,并确保所有的.jars是根据我们自己的盒子上的代码副本构建的.(也就是说,我们希望它的行为基本上就像我们使用compile(project(":otherproject"))而不是编译("group:otherproject:1.0-SNAPSHOT")或其他一些.)
我对Gradle很新,而且我完全有可能错过一些非常明显的东西,但我还没有找到一个很好的方法来处理这个问题.
我们可以做一些事情,通过从我们的Maven存储库中拉出.jars来构建它的依赖集在一个文件中,并通过在另一个文件中使用其兄弟子项目来构建它的依赖集,但这看起来像是DRY违规.(在这种情况下,我们有两个不同的位置来管理依赖项列表.)
我们可以创建子项目的构建脚本,以便始终从Maven存储库中提取并让超级项目的构建脚本包含每个子项目的部分,这些部分覆盖子项目中的依赖项,但这与前一个选项一样多.
我想也许可以让superproject实际内省并根据需要修改每个子项目的依赖项列表(超级项目中的代码应该可以访问将Maven工件的依赖项转换为相应的依赖项所需的所有信息.兄弟子项目,我想),但在仔细研究之后,我不确定如何去做.
我希望你们能帮忙.谢谢!