feat(responses): implement responses and add a test
- implement rendering test for responses and requests - redo the API a bit to make responses and requests consistent
This commit is contained in:
parent
5cb5b5c4e9
commit
8a80b4e359
3 changed files with 257 additions and 104 deletions
|
@ -24,4 +24,3 @@ IsDelta="True"
|
||||||
</updatecheck>
|
</updatecheck>
|
||||||
</app>
|
</app>
|
||||||
</response>
|
</response>
|
||||||
|
|
||||||
|
|
|
@ -1,140 +1,250 @@
|
||||||
/*
|
/*
|
||||||
Package that implements the Google omaha protocol.
|
Package that implements the Google omaha protocol.
|
||||||
|
|
||||||
Omaha is a request/response protocol using XML. Requests are made by
|
Omaha is a request/response protocol using XML. Requests are made by
|
||||||
clients and responses are given by the Omaha server.
|
clients and responses are given by the Omaha server.
|
||||||
http://code.google.com/p/omaha/wiki/ServerProtocol
|
http://code.google.com/p/omaha/wiki/ServerProtocol
|
||||||
The
|
The
|
||||||
*/
|
*/
|
||||||
package omaha
|
package omaha
|
||||||
|
|
||||||
import "encoding/xml"
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
)
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Os Os
|
XMLName xml.Name `xml:"request"`
|
||||||
Apps []App `xml:"app"`
|
Os Os `xml:"os"`
|
||||||
Protocol string `xml:"protocol,attr"`
|
Apps []*App `xml:"app"`
|
||||||
Version string `xml:"version,attr,omitempty"`
|
Protocol string `xml:"protocol,attr"`
|
||||||
IsMachine string `xml:"ismachine,attr,omitempty"`
|
Version string `xml:"version,attr,omitempty"`
|
||||||
SessionId string `xml:"sessionid,attr,omitempty"`
|
IsMachine string `xml:"ismachine,attr,omitempty"`
|
||||||
UserId string `xml:"userid,attr,omitempty"`
|
SessionId string `xml:"sessionid,attr,omitempty"`
|
||||||
InstallSource string `xml:"installsource,attr,omitempty"`
|
UserId string `xml:"userid,attr,omitempty"`
|
||||||
TestSource string `xml:"testsource,attr,omitempty"`
|
InstallSource string `xml:"installsource,attr,omitempty"`
|
||||||
RequestId string `xml:"requestid,attr,omitempty"`
|
TestSource string `xml:"testsource,attr,omitempty"`
|
||||||
UpdaterVersion string `xml:"updaterversion,attr,omitempty"`
|
RequestId string `xml:"requestid,attr,omitempty"`
|
||||||
|
UpdaterVersion string `xml:"updaterversion,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRequest(os *Os, app *App) *Request {
|
func NewRequest(version string, platform string, sp string, arch string) *Request {
|
||||||
r := new(Request)
|
r := new(Request)
|
||||||
r.Protocol = "3.0"
|
r.Protocol = "3.0"
|
||||||
r.AddApp(app)
|
r.Os.Version = version
|
||||||
r.Os = *os
|
r.Os.Platform = platform
|
||||||
|
r.Os.Sp = sp
|
||||||
|
r.Os.Arch = arch
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Request) AddApp(a *App) {
|
func (r *Request) AddApp(id string, version string) *App {
|
||||||
r.Apps = append(r.Apps, *a)
|
a := NewApp(id)
|
||||||
}
|
|
||||||
|
|
||||||
// app element
|
|
||||||
type App struct {
|
|
||||||
XMLName xml.Name `xml:"app"`
|
|
||||||
UpdateCheck *UpdateCheck `xml:"updatecheck"`
|
|
||||||
Event *Event `xml:"event"`
|
|
||||||
Ping *Ping `xml:"ping"`
|
|
||||||
Id string `xml:"appid,attr,omitempty"`
|
|
||||||
Version string `xml:"version,attr,omitempty"`
|
|
||||||
NextVersion string `xml:"nextversion,attr,omitempty"`
|
|
||||||
Lang string `xml:"lang,attr,omitempty"`
|
|
||||||
Client string `xml:"client,attr,omitempty"`
|
|
||||||
InstallAge string `xml:"installage,attr,omitempty"`
|
|
||||||
FromTrack string `xml:"from_track,attr,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewApp(id string, version string) *App {
|
|
||||||
a := new(App)
|
|
||||||
a.Id = id
|
|
||||||
a.Version = version
|
a.Version = version
|
||||||
|
r.Apps = append(r.Apps, a)
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateCheck struct {
|
/* Response
|
||||||
XMLName xml.Name `xml:"updatecheck"`
|
*/
|
||||||
TargetVersionPrefix string `xml:"targetversionprefix,attr,omitempty"`
|
type Response struct {
|
||||||
|
XMLName xml.Name `xml:"response"`
|
||||||
|
DayStart DayStart `xml:"daystart"`
|
||||||
|
Apps []*App `xml:"app"`
|
||||||
|
Protocol string `xml:"protocol,attr"`
|
||||||
|
Server string `xml:"server,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AddUpdateCheck() {
|
func NewResponse(server string) *Response {
|
||||||
|
r := &Response{Server: server, Protocol: "3.0"}
|
||||||
|
r.DayStart.ElapsedSeconds = "0"
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
type DayStart struct {
|
||||||
|
ElapsedSeconds string `xml:"elapsed_seconds,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) AddApp(id string) *App {
|
||||||
|
a := NewApp(id)
|
||||||
|
r.Apps = append(r.Apps, a)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
XMLName xml.Name `xml:"app"`
|
||||||
|
Ping *Ping `xml:"ping"`
|
||||||
|
UpdateCheck *UpdateCheck `xml:"updatecheck"`
|
||||||
|
Urls *Urls `xml:"urls"`
|
||||||
|
Manifest *Manifest `xml:"manifest"`
|
||||||
|
Event *Event `xml:"event"`
|
||||||
|
Id string `xml:"appid,attr,omitempty"`
|
||||||
|
Version string `xml:"version,attr,omitempty"`
|
||||||
|
NextVersion string `xml:"nextversion,attr,omitempty"`
|
||||||
|
Lang string `xml:"lang,attr,omitempty"`
|
||||||
|
Client string `xml:"client,attr,omitempty"`
|
||||||
|
InstallAge string `xml:"installage,attr,omitempty"`
|
||||||
|
FromTrack string `xml:"from_track,attr,omitempty"`
|
||||||
|
Status string `xml:"status,attr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApp(id string) *App {
|
||||||
|
a := &App{Id: id}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) AddUpdateCheck() *UpdateCheck {
|
||||||
a.UpdateCheck = new(UpdateCheck)
|
a.UpdateCheck = new(UpdateCheck)
|
||||||
|
return a.UpdateCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) AddPing() *Ping {
|
||||||
|
a.Ping = new(Ping)
|
||||||
|
return a.Ping
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) AddUrl(codebase string) *Url {
|
||||||
|
if a.Urls == nil {
|
||||||
|
a.Urls = new(Urls)
|
||||||
|
}
|
||||||
|
u := new(Url)
|
||||||
|
u.CodeBase = codebase
|
||||||
|
a.Urls.Urls = append(a.Urls.Urls, *u)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) AddManifest(version string) *Manifest {
|
||||||
|
a.Manifest = &Manifest{Version: version}
|
||||||
|
return a.Manifest
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateCheck struct {
|
||||||
|
XMLName xml.Name `xml:"updatecheck"`
|
||||||
|
TargetVersionPrefix string `xml:"targetversionprefix,attr,omitempty"`
|
||||||
|
Status string `xml:"status,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ping struct {
|
type Ping struct {
|
||||||
XMLName xml.Name `xml:"ping"`
|
XMLName xml.Name `xml:"ping"`
|
||||||
LastReportDays string `xml:"r,attr,omitempty"`
|
LastReportDays string `xml:"r,attr,omitempty"`
|
||||||
|
Status string `xml:"status,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Os struct {
|
type Os struct {
|
||||||
XMLName xml.Name `xml:"os"`
|
XMLName xml.Name `xml:"os"`
|
||||||
Platform string `xml:"platform,attr,omitempty"`
|
Platform string `xml:"platform,attr,omitempty"`
|
||||||
Version string `xml:"version,attr,omitempty"`
|
Version string `xml:"version,attr,omitempty"`
|
||||||
Sp string `xml:"sp,attr,omitempty"`
|
Sp string `xml:"sp,attr,omitempty"`
|
||||||
Arch string `xml:"arch,attr,omitempty"`
|
Arch string `xml:"arch,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOs(platform string, version string, sp string, arch string) *Os {
|
func NewOs(platform string, version string, sp string, arch string) *Os {
|
||||||
o := new(Os)
|
o := new(Os)
|
||||||
o.Platform = platform
|
|
||||||
o.Version = version
|
o.Version = version
|
||||||
|
o.Platform = platform
|
||||||
o.Sp = sp
|
o.Sp = sp
|
||||||
o.Arch = arch
|
o.Arch = arch
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AddPing() {
|
|
||||||
}
|
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
XMLName xml.Name `xml:"event"`
|
XMLName xml.Name `xml:"event"`
|
||||||
Type string `xml:"eventtype,attr,omitempty"`
|
Type string `xml:"eventtype,attr,omitempty"`
|
||||||
Result string `xml:"eventresult,attr,omitempty"`
|
Result string `xml:"eventresult,attr,omitempty"`
|
||||||
PreviousVersion string `xml:"previousversion,attr,omitempty"`
|
PreviousVersion string `xml:"previousversion,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var EventTypes = map[int] string {
|
type Urls struct {
|
||||||
0: "unknown",
|
XMLName xml.Name `xml:"urls"`
|
||||||
1: "download complete",
|
Urls []Url `xml:"url"`
|
||||||
2: "install complete",
|
}
|
||||||
3: "update complete",
|
|
||||||
4: "uninstall",
|
type Url struct {
|
||||||
5: "download started",
|
XMLName xml.Name `xml:"url"`
|
||||||
6: "install started",
|
CodeBase string `xml:"codebase,attr"`
|
||||||
9: "new application install started",
|
}
|
||||||
10: "setup started",
|
|
||||||
11: "setup finished",
|
type Manifest struct {
|
||||||
12: "update application started",
|
XMLName xml.Name `xml:"manifest"`
|
||||||
13: "update download started",
|
Packages Packages `xml:"packages"`
|
||||||
14: "update download finished",
|
Actions Actions `xml:"actions"`
|
||||||
15: "update installer started",
|
Version string `xml:"version,attr"`
|
||||||
16: "setup update begin",
|
}
|
||||||
17: "setup update complete",
|
|
||||||
20: "register product complete",
|
type Packages struct {
|
||||||
30: "OEM install first check",
|
XMLName xml.Name `xml:"packages"`
|
||||||
40: "app-specific command started",
|
Packages []Package `xml:"package"`
|
||||||
41: "app-specific command ended",
|
}
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
XMLName xml.Name `xml:"package"`
|
||||||
|
Hash string `xml:"hash,attr"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Size string `xml:"size,attr"`
|
||||||
|
Required bool `xml:"required,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manifest) AddPackage(hash string, name string, size string, required bool) *Package {
|
||||||
|
p := &Package{Hash: hash, Name: name, Size: size, Required: required}
|
||||||
|
m.Packages.Packages = append(m.Packages.Packages, *p)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
type Actions struct {
|
||||||
|
XMLName xml.Name `xml:"actions"`
|
||||||
|
Actions []Action `xml:"action"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action struct {
|
||||||
|
XMLName xml.Name `xml:"action"`
|
||||||
|
Event string `xml:"event,attr"`
|
||||||
|
ChromeOSVersion string `xml:"ChromeOSVersion,attr"`
|
||||||
|
sha256 string `xml:"sha256,attr"`
|
||||||
|
NeedsAdmin bool `xml:"needsadmin,attr"`
|
||||||
|
IsDelta bool `xml:"IsDelta,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manifest) AddAction(event string) *Action {
|
||||||
|
a := &Action{Event: event}
|
||||||
|
m.Actions.Actions = append(m.Actions.Actions, *a)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
var EventTypes = map[int]string{
|
||||||
|
0: "unknown",
|
||||||
|
1: "download complete",
|
||||||
|
2: "install complete",
|
||||||
|
3: "update complete",
|
||||||
|
4: "uninstall",
|
||||||
|
5: "download started",
|
||||||
|
6: "install started",
|
||||||
|
9: "new application install started",
|
||||||
|
10: "setup started",
|
||||||
|
11: "setup finished",
|
||||||
|
12: "update application started",
|
||||||
|
13: "update download started",
|
||||||
|
14: "update download finished",
|
||||||
|
15: "update installer started",
|
||||||
|
16: "setup update begin",
|
||||||
|
17: "setup update complete",
|
||||||
|
20: "register product complete",
|
||||||
|
30: "OEM install first check",
|
||||||
|
40: "app-specific command started",
|
||||||
|
41: "app-specific command ended",
|
||||||
100: "setup failure",
|
100: "setup failure",
|
||||||
102: "COM server failure",
|
102: "COM server failure",
|
||||||
103: "setup update failure",
|
103: "setup update failure",
|
||||||
}
|
}
|
||||||
|
|
||||||
var EventResults = map[int] string {
|
var EventResults = map[int]string{
|
||||||
0: "error",
|
0: "error",
|
||||||
1: "success",
|
1: "success",
|
||||||
2: "success reboot",
|
2: "success reboot",
|
||||||
3: "success restart browser",
|
3: "success restart browser",
|
||||||
4: "cancelled",
|
4: "cancelled",
|
||||||
5: "error installer MSI",
|
5: "error installer MSI",
|
||||||
6: "error installer other",
|
6: "error installer other",
|
||||||
7: "noupdate",
|
7: "noupdate",
|
||||||
8: "error installer system",
|
8: "error installer system",
|
||||||
9: "update deferred",
|
9: "update deferred",
|
||||||
10: "handoff error",
|
10: "handoff error",
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package omaha
|
package omaha
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"fmt"
|
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOmahaRequestUpdateCheck(t *testing.T) {
|
func TestOmahaRequestUpdateCheck(t *testing.T) {
|
||||||
|
@ -45,14 +45,58 @@ func TestOmahaRequestUpdateCheck(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleOmaha_NewResponse() {
|
||||||
|
response := NewResponse("unit-test")
|
||||||
|
app := response.AddApp("{52F1B9BC-D31A-4D86-9276-CBC256AADF9A}")
|
||||||
|
app.Status = "ok"
|
||||||
|
p := app.AddPing()
|
||||||
|
p.Status = "ok"
|
||||||
|
u := app.AddUpdateCheck()
|
||||||
|
u.Status = "ok"
|
||||||
|
app.AddUrl("http://localhost/updates")
|
||||||
|
m := app.AddManifest("9999.0.0")
|
||||||
|
m.AddPackage("+LXvjiaPkeYDLHoNKlf9qbJwvnk=", "update.gz", "67546213", true)
|
||||||
|
a := m.AddAction("postinstall")
|
||||||
|
a.ChromeOSVersion = "9999.0.0"
|
||||||
|
a.sha256 = "0VAlQW3RE99SGtSB5R4m08antAHO8XDoBMKDyxQT/Mg="
|
||||||
|
a.NeedsAdmin = false
|
||||||
|
a.IsDelta = true
|
||||||
|
|
||||||
|
if raw, err := xml.MarshalIndent(response, "", " "); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s%s\n", xml.Header, raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
//
|
||||||
|
// <response protocol="3.0" server="unit-test">
|
||||||
|
// <daystart elapsed_seconds="0"></daystart>
|
||||||
|
// <app appid="{52F1B9BC-D31A-4D86-9276-CBC256AADF9A}" status="ok">
|
||||||
|
// <ping status="ok"></ping>
|
||||||
|
// <updatecheck status="ok"></updatecheck>
|
||||||
|
// <urls>
|
||||||
|
// <url codebase="http://localhost/updates"></url>
|
||||||
|
// </urls>
|
||||||
|
// <manifest version="9999.0.0">
|
||||||
|
// <packages>
|
||||||
|
// <package hash="+LXvjiaPkeYDLHoNKlf9qbJwvnk=" name="update.gz" size="67546213" required="true"></package>
|
||||||
|
// </packages>
|
||||||
|
// <actions>
|
||||||
|
// <action event="postinstall" ChromeOSVersion="" needsadmin="false" IsDelta="false"></action>
|
||||||
|
// </actions>
|
||||||
|
// </manifest>
|
||||||
|
// </app>
|
||||||
|
// </response>
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleOmaha_NewRequest() {
|
func ExampleOmaha_NewRequest() {
|
||||||
os := NewOs("linux", "3.0", "", "x64")
|
request := NewRequest("Indy", "Chrome OS", "ForcedUpdate_x86_64", "")
|
||||||
|
app := request.AddApp("{27BD862E-8AE8-4886-A055-F7F1A6460627}", "1.0.0.0")
|
||||||
app := NewApp("{27BD862E-8AE8-4886-A055-F7F1A6460627}", "1.0.0.0")
|
|
||||||
app.AddUpdateCheck()
|
app.AddUpdateCheck()
|
||||||
|
|
||||||
request := NewRequest(os, app)
|
|
||||||
|
|
||||||
if raw, err := xml.MarshalIndent(request, "", " "); err != nil {
|
if raw, err := xml.MarshalIndent(request, "", " "); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
|
@ -63,10 +107,10 @@ func ExampleOmaha_NewRequest() {
|
||||||
// Output:
|
// Output:
|
||||||
// <?xml version="1.0" encoding="UTF-8"?>
|
// <?xml version="1.0" encoding="UTF-8"?>
|
||||||
//
|
//
|
||||||
// <Request protocol="3.0">
|
// <request protocol="3.0">
|
||||||
// <os platform="linux" version="3.0" arch="x64"></os>
|
// <os platform="Chrome OS" version="Indy" sp="ForcedUpdate_x86_64"></os>
|
||||||
// <app appid="{27BD862E-8AE8-4886-A055-F7F1A6460627}" version="1.0.0.0">
|
// <app appid="{27BD862E-8AE8-4886-A055-F7F1A6460627}" version="1.0.0.0">
|
||||||
// <updatecheck></updatecheck>
|
// <updatecheck></updatecheck>
|
||||||
// </app>
|
// </app>
|
||||||
// </Request>
|
// </request>
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue