1package api_test
2
3import (
4	"compress/gzip"
5	"io/ioutil"
6	"net/http"
7	"os"
8	"path/filepath"
9	"time"
10
11	. "github.com/concourse/concourse/atc/testhelpers"
12	"github.com/concourse/go-archive/archivetest"
13	. "github.com/onsi/ginkgo"
14	. "github.com/onsi/gomega"
15)
16
17var _ = Describe("CLI Downloads API", func() {
18	var (
19		response *http.Response
20	)
21
22	BeforeEach(func() {
23		tgz := filepath.Join(cliDownloadsDir, "fly-darwin-amd64.tgz")
24		zip := filepath.Join(cliDownloadsDir, "fly-windows-amd64.zip")
25
26		unixArchive := archivetest.Archive{
27			{
28				Name: "some-file",
29				Body: "skipped!",
30			},
31			{
32				Name:    "fly",
33				Body:    "soi soi soi",
34				ModTime: time.Date(1991, time.June, 3, 5, 30, 45, 10, time.UTC),
35			},
36		}
37
38		windowsArchive := archivetest.Archive{
39			{
40				Name: "some-file",
41				Body: "skipped!",
42			},
43			{
44				Name:    "fly.exe",
45				Body:    "soi soi soi.notavirus.bat",
46				ModTime: time.Date(1989, time.June, 29, 5, 30, 44, 10, time.UTC),
47			},
48		}
49
50		tgzFile, err := os.Create(tgz)
51		Expect(err).NotTo(HaveOccurred())
52
53		gzWriter := gzip.NewWriter(tgzFile)
54
55		err = unixArchive.WriteTar(gzWriter)
56		Expect(err).NotTo(HaveOccurred())
57
58		Expect(gzWriter.Close()).To(Succeed())
59		Expect(tgzFile.Close()).To(Succeed())
60
61		zipFile, err := os.Create(zip)
62		Expect(err).NotTo(HaveOccurred())
63
64		err = windowsArchive.WriteZip(zipFile)
65		Expect(err).NotTo(HaveOccurred())
66
67	})
68
69	AfterEach(func() {
70		_ = os.RemoveAll(cliDownloadsDir)
71	})
72
73	Describe("GET /api/v1/cli?platform=darwin&arch=amd64", func() {
74		JustBeforeEach(func() {
75			req, err := http.NewRequest("GET", server.URL+"/api/v1/cli?platform=darwin&arch=amd64", nil)
76			Expect(err).NotTo(HaveOccurred())
77
78			response, err = client.Do(req)
79			Expect(err).NotTo(HaveOccurred())
80		})
81
82		It("returns 200", func() {
83			Expect(response.StatusCode).To(Equal(http.StatusOK))
84		})
85
86		It("returns the a response with expected headers", func() {
87			expectedHeaderEntries := map[string]string{
88				"Content-Type":        "application/octet-stream",
89				"Content-Length":      "11",
90				"Content-Disposition": "attachment; filename=fly",
91				"Last-Modified":       "Mon, 03 Jun 1991 05:30:45 GMT",
92			}
93
94			Expect(response).Should(IncludeHeaderEntries(expectedHeaderEntries))
95		})
96
97		It("returns the file binary", func() {
98			Expect(ioutil.ReadAll(response.Body)).To(Equal([]byte("soi soi soi")))
99		})
100	})
101
102	Describe("GET /api/v1/cli?platform=windows&arch=amd64", func() {
103		JustBeforeEach(func() {
104			req, err := http.NewRequest("GET", server.URL+"/api/v1/cli?platform=windows&arch=amd64", nil)
105			Expect(err).NotTo(HaveOccurred())
106
107			response, err = client.Do(req)
108			Expect(err).NotTo(HaveOccurred())
109		})
110
111		It("returns 200", func() {
112			Expect(response.StatusCode).To(Equal(http.StatusOK))
113		})
114
115		It("returns the a response with expected headers", func() {
116			expectedHeaderEntries := map[string]string{
117				"Content-Type":        "application/octet-stream",
118				"Content-Length":      "25",
119				"Content-Disposition": "attachment; filename=fly.exe",
120				"Last-Modified":       "Thu, 29 Jun 1989 05:30:44 GMT",
121			}
122			Expect(response).Should(IncludeHeaderEntries(expectedHeaderEntries))
123		})
124
125		It("returns the file binary", func() {
126			Expect(ioutil.ReadAll(response.Body)).To(Equal([]byte("soi soi soi.notavirus.bat")))
127		})
128	})
129
130	Describe("GET /api/v1/cli?platform=Darwin&arch=amd64", func() {
131		JustBeforeEach(func() {
132			req, err := http.NewRequest("GET", server.URL+"/api/v1/cli?platform=Darwin&arch=amd64", nil)
133			Expect(err).NotTo(HaveOccurred())
134
135			response, err = client.Do(req)
136			Expect(err).NotTo(HaveOccurred())
137		})
138
139		It("returns 200", func() {
140			Expect(response.StatusCode).To(Equal(http.StatusOK))
141		})
142
143		It("returns the file binary", func() {
144			Expect(ioutil.ReadAll(response.Body)).To(Equal([]byte("soi soi soi")))
145		})
146	})
147
148	Describe("GET /api/v1/cli?platform=Windows&arch=amd64", func() {
149		JustBeforeEach(func() {
150			req, err := http.NewRequest("GET", server.URL+"/api/v1/cli?platform=Windows&arch=amd64", nil)
151			Expect(err).NotTo(HaveOccurred())
152
153			response, err = client.Do(req)
154			Expect(err).NotTo(HaveOccurred())
155		})
156
157		It("returns 200", func() {
158			Expect(response.StatusCode).To(Equal(http.StatusOK))
159		})
160
161		It("returns the file binary", func() {
162			Expect(ioutil.ReadAll(response.Body)).To(Equal([]byte("soi soi soi.notavirus.bat")))
163		})
164	})
165
166	Describe("GET /api/v1/cli?platform=darwin&arch=../darwin/amd64", func() {
167		JustBeforeEach(func() {
168			req, err := http.NewRequest("GET", server.URL+"/api/v1/cli?platform=darwin&arch=../darwin/amd64", nil)
169			Expect(err).NotTo(HaveOccurred())
170
171			response, err = client.Do(req)
172			Expect(err).NotTo(HaveOccurred())
173		})
174
175		It("returns Bad Request", func() {
176			Expect(response.StatusCode).To(Equal(http.StatusBadRequest))
177		})
178	})
179
180	Describe("GET /api/v1/cli?platform=../etc/passwd&arch=amd64", func() {
181		JustBeforeEach(func() {
182			req, err := http.NewRequest("GET", server.URL+"/api/v1/cli?platform=../etc/passwd&arch=amd64", nil)
183			Expect(err).NotTo(HaveOccurred())
184
185			response, err = client.Do(req)
186			Expect(err).NotTo(HaveOccurred())
187		})
188
189		It("returns Bad Request", func() {
190			Expect(response.StatusCode).To(Equal(http.StatusBadRequest))
191		})
192	})
193})
194